Index: head/contrib/compiler-rt =================================================================== --- head/contrib/compiler-rt (revision 326908) +++ head/contrib/compiler-rt (revision 326909) Property changes on: head/contrib/compiler-rt ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /vendor/compiler-rt/dist:r326471-326907 Index: head/contrib/libc++ =================================================================== --- head/contrib/libc++ (revision 326908) +++ head/contrib/libc++ (revision 326909) Property changes on: head/contrib/libc++ ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /vendor/libc++/dist:r326471-326907 Index: head/contrib/llvm/lib/Target/BPF/BPFISelLowering.cpp =================================================================== --- head/contrib/llvm/lib/Target/BPF/BPFISelLowering.cpp (revision 326908) +++ head/contrib/llvm/lib/Target/BPF/BPFISelLowering.cpp (revision 326909) @@ -1,607 +1,611 @@ //===-- BPFISelLowering.cpp - BPF DAG Lowering Implementation ------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the interfaces that BPF uses to lower LLVM code into a // selection DAG. // //===----------------------------------------------------------------------===// #include "BPFISelLowering.h" #include "BPF.h" #include "BPFSubtarget.h" #include "BPFTargetMachine.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; #define DEBUG_TYPE "bpf-lower" static void fail(const SDLoc &DL, SelectionDAG &DAG, const Twine &Msg) { MachineFunction &MF = DAG.getMachineFunction(); DAG.getContext()->diagnose( DiagnosticInfoUnsupported(*MF.getFunction(), Msg, DL.getDebugLoc())); } static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *Msg, SDValue Val) { MachineFunction &MF = DAG.getMachineFunction(); std::string Str; raw_string_ostream OS(Str); OS << Msg; Val->print(OS); OS.flush(); DAG.getContext()->diagnose( DiagnosticInfoUnsupported(*MF.getFunction(), Str, DL.getDebugLoc())); } BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM, const BPFSubtarget &STI) : TargetLowering(TM) { // Set up the register classes. addRegisterClass(MVT::i64, &BPF::GPRRegClass); // Compute derived properties from the register classes computeRegisterProperties(STI.getRegisterInfo()); setStackPointerRegisterToSaveRestore(BPF::R11); setOperationAction(ISD::BR_CC, MVT::i64, Custom); setOperationAction(ISD::BR_JT, MVT::Other, Expand); setOperationAction(ISD::BRIND, MVT::Other, Expand); setOperationAction(ISD::BRCOND, MVT::Other, Expand); setOperationAction(ISD::SETCC, MVT::i64, Expand); setOperationAction(ISD::SELECT, MVT::i64, Expand); setOperationAction(ISD::SELECT_CC, MVT::i64, Custom); setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom); setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); setOperationAction(ISD::SDIVREM, MVT::i64, Expand); setOperationAction(ISD::UDIVREM, MVT::i64, Expand); setOperationAction(ISD::SREM, MVT::i64, Expand); setOperationAction(ISD::UREM, MVT::i64, Expand); setOperationAction(ISD::MULHU, MVT::i64, Expand); setOperationAction(ISD::MULHS, MVT::i64, Expand); setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); setOperationAction(ISD::ADDC, MVT::i64, Expand); setOperationAction(ISD::ADDE, MVT::i64, Expand); setOperationAction(ISD::SUBC, MVT::i64, Expand); setOperationAction(ISD::SUBE, MVT::i64, Expand); setOperationAction(ISD::ROTR, MVT::i64, Expand); setOperationAction(ISD::ROTL, MVT::i64, Expand); setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand); setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand); setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand); setOperationAction(ISD::CTTZ, MVT::i64, Custom); setOperationAction(ISD::CTLZ, MVT::i64, Custom); setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Custom); setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Custom); setOperationAction(ISD::CTPOP, MVT::i64, Expand); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Expand); // Extended load operations for i1 types must be promoted for (MVT VT : MVT::integer_valuetypes()) { setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote); setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote); setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i8, Expand); setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i16, Expand); setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i32, Expand); } setBooleanContents(ZeroOrOneBooleanContent); // Function alignments (log2) setMinFunctionAlignment(3); setPrefFunctionAlignment(3); // inline memcpy() for kernel to see explicit copy MaxStoresPerMemset = MaxStoresPerMemsetOptSize = 128; MaxStoresPerMemcpy = MaxStoresPerMemcpyOptSize = 128; MaxStoresPerMemmove = MaxStoresPerMemmoveOptSize = 128; } bool BPFTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { return false; } SDValue BPFTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { case ISD::BR_CC: return LowerBR_CC(Op, DAG); case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); default: llvm_unreachable("unimplemented operand"); } } // Calling Convention Implementation #include "BPFGenCallingConv.inc" SDValue BPFTargetLowering::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"); case CallingConv::C: case CallingConv::Fast: break; } MachineFunction &MF = DAG.getMachineFunction(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); // Assign locations to all of the incoming arguments. SmallVector ArgLocs; CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); CCInfo.AnalyzeFormalArguments(Ins, CC_BPF64); for (auto &VA : ArgLocs) { if (VA.isRegLoc()) { // Arguments passed in registers EVT RegVT = VA.getLocVT(); switch (RegVT.getSimpleVT().SimpleTy) { default: { errs() << "LowerFormalArguments Unhandled argument type: " << RegVT.getEVTString() << '\n'; llvm_unreachable(0); } case MVT::i64: unsigned VReg = RegInfo.createVirtualRegister(&BPF::GPRRegClass); RegInfo.addLiveIn(VA.getLocReg(), VReg); SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, VReg, RegVT); // If this is an 8/16/32-bit value, it is really passed promoted to 64 // bits. Insert an assert[sz]ext to capture this, then truncate to the // right size. if (VA.getLocInfo() == CCValAssign::SExt) ArgValue = DAG.getNode(ISD::AssertSext, DL, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); else if (VA.getLocInfo() == CCValAssign::ZExt) ArgValue = DAG.getNode(ISD::AssertZext, DL, RegVT, ArgValue, DAG.getValueType(VA.getValVT())); if (VA.getLocInfo() != CCValAssign::Full) ArgValue = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), ArgValue); InVals.push_back(ArgValue); } } else { fail(DL, DAG, "defined with too many args"); InVals.push_back(DAG.getConstant(0, DL, VA.getLocVT())); } } if (IsVarArg || MF.getFunction()->hasStructRetAttr()) { fail(DL, DAG, "functions with VarArgs or StructRet are not supported"); } return Chain; } const unsigned BPFTargetLowering::MaxArgs = 5; SDValue BPFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl &InVals) const { SelectionDAG &DAG = CLI.DAG; auto &Outs = CLI.Outs; auto &OutVals = CLI.OutVals; auto &Ins = CLI.Ins; SDValue Chain = CLI.Chain; SDValue Callee = CLI.Callee; bool &IsTailCall = CLI.IsTailCall; CallingConv::ID CallConv = CLI.CallConv; bool IsVarArg = CLI.IsVarArg; MachineFunction &MF = DAG.getMachineFunction(); // BPF target does not support tail call optimization. IsTailCall = false; switch (CallConv) { default: report_fatal_error("Unsupported calling convention"); case CallingConv::Fast: case CallingConv::C: break; } // Analyze operands of the call, assigning locations to each operand. SmallVector ArgLocs; CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); CCInfo.AnalyzeCallOperands(Outs, CC_BPF64); unsigned NumBytes = CCInfo.getNextStackOffset(); if (Outs.size() > MaxArgs) fail(CLI.DL, DAG, "too many args to ", Callee); for (auto &Arg : Outs) { ISD::ArgFlagsTy Flags = Arg.Flags; if (!Flags.isByVal()) continue; fail(CLI.DL, DAG, "pass by value not supported ", Callee); } auto PtrVT = getPointerTy(MF.getDataLayout()); Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL); SmallVector, MaxArgs> RegsToPass; // Walk arg assignments for (unsigned i = 0, e = std::min(static_cast(ArgLocs.size()), MaxArgs); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; SDValue Arg = OutVals[i]; // Promote the value if needed. switch (VA.getLocInfo()) { default: llvm_unreachable("Unknown loc info"); case CCValAssign::Full: break; case CCValAssign::SExt: Arg = DAG.getNode(ISD::SIGN_EXTEND, CLI.DL, VA.getLocVT(), Arg); break; case CCValAssign::ZExt: Arg = DAG.getNode(ISD::ZERO_EXTEND, CLI.DL, VA.getLocVT(), Arg); break; case CCValAssign::AExt: Arg = DAG.getNode(ISD::ANY_EXTEND, CLI.DL, VA.getLocVT(), Arg); break; } // Push arguments into RegsToPass vector if (VA.isRegLoc()) RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); else llvm_unreachable("call arg pass bug"); } SDValue InFlag; // Build a sequence of copy-to-reg nodes chained together with token chain and // flag operands which copy the outgoing args into registers. The InFlag in // necessary since all emitted instructions must be stuck together. for (auto &Reg : RegsToPass) { Chain = DAG.getCopyToReg(Chain, CLI.DL, Reg.first, Reg.second, InFlag); InFlag = Chain.getValue(1); } // If the callee is a GlobalAddress node (quite common, every direct call is) // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. // Likewise ExternalSymbol -> TargetExternalSymbol. if (GlobalAddressSDNode *G = dyn_cast(Callee)) { auto GV = G->getGlobal(); fail(CLI.DL, DAG, "A call to global function '" + StringRef(GV->getName()) + "' is not supported. " + (GV->isDeclaration() ? "Only calls to predefined BPF helpers are allowed." : "Please use __attribute__((always_inline) to make sure" " this function is inlined.")); Callee = DAG.getTargetGlobalAddress(G->getGlobal(), CLI.DL, PtrVT, G->getOffset(), 0); } else if (ExternalSymbolSDNode *E = dyn_cast(Callee)) { Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, 0); fail(CLI.DL, DAG, Twine("A call to built-in function '" + StringRef(E->getSymbol()) + "' is not supported.")); } // Returns a chain & a flag for retval copy to use. SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); SmallVector Ops; Ops.push_back(Chain); Ops.push_back(Callee); // Add argument registers to the end of the list so that they are // known live into the call. for (auto &Reg : RegsToPass) Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType())); if (InFlag.getNode()) Ops.push_back(InFlag); Chain = DAG.getNode(BPFISD::CALL, CLI.DL, NodeTys, Ops); InFlag = Chain.getValue(1); // Create the CALLSEQ_END node. Chain = DAG.getCALLSEQ_END( Chain, DAG.getConstant(NumBytes, CLI.DL, PtrVT, true), DAG.getConstant(0, CLI.DL, PtrVT, true), InFlag, CLI.DL); InFlag = Chain.getValue(1); // Handle result values, copying them out of physregs into vregs that we // return. return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, CLI.DL, DAG, InVals); } SDValue BPFTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl &Outs, const SmallVectorImpl &OutVals, const SDLoc &DL, SelectionDAG &DAG) const { unsigned Opc = BPFISD::RET_FLAG; // CCValAssign - represent the assignment of the return value to a location SmallVector RVLocs; MachineFunction &MF = DAG.getMachineFunction(); // CCState - Info about the registers and stack slot. CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); if (MF.getFunction()->getReturnType()->isAggregateType()) { fail(DL, DAG, "only integer returns supported"); return DAG.getNode(Opc, DL, MVT::Other, Chain); } // Analize return values. CCInfo.AnalyzeReturn(Outs, RetCC_BPF64); SDValue Flag; SmallVector RetOps(1, Chain); // Copy the result values into the output registers. for (unsigned i = 0; i != RVLocs.size(); ++i) { CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Flag); // Guarantee that all emitted copies are stuck together, // avoiding something bad. Flag = Chain.getValue(1); RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); } RetOps[0] = Chain; // Update chain. // Add the flag if we have it. if (Flag.getNode()) RetOps.push_back(Flag); return DAG.getNode(Opc, DL, MVT::Other, RetOps); } SDValue BPFTargetLowering::LowerCallResult( SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); // Assign locations to each value returned by this call. SmallVector RVLocs; CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); if (Ins.size() >= 2) { fail(DL, DAG, "only small returns supported"); for (unsigned i = 0, e = Ins.size(); i != e; ++i) InVals.push_back(DAG.getConstant(0, DL, Ins[i].VT)); return DAG.getCopyFromReg(Chain, DL, 1, Ins[0].VT, InFlag).getValue(1); } CCInfo.AnalyzeCallResult(Ins, RetCC_BPF64); // Copy all of the result registers out of their specified physreg. for (auto &Val : RVLocs) { Chain = DAG.getCopyFromReg(Chain, DL, Val.getLocReg(), Val.getValVT(), InFlag).getValue(1); InFlag = Chain.getValue(2); InVals.push_back(Chain.getValue(0)); } return Chain; } static void NegateCC(SDValue &LHS, SDValue &RHS, ISD::CondCode &CC) { switch (CC) { default: break; case ISD::SETULT: case ISD::SETULE: case ISD::SETLT: case ISD::SETLE: CC = ISD::getSetCCSwappedOperands(CC); std::swap(LHS, RHS); break; } } SDValue BPFTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const { SDValue Chain = Op.getOperand(0); ISD::CondCode CC = cast(Op.getOperand(1))->get(); SDValue LHS = Op.getOperand(2); SDValue RHS = Op.getOperand(3); SDValue Dest = Op.getOperand(4); SDLoc DL(Op); NegateCC(LHS, RHS, CC); return DAG.getNode(BPFISD::BR_CC, DL, Op.getValueType(), Chain, LHS, RHS, DAG.getConstant(CC, DL, MVT::i64), Dest); } SDValue BPFTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { SDValue LHS = Op.getOperand(0); SDValue RHS = Op.getOperand(1); SDValue TrueV = Op.getOperand(2); SDValue FalseV = Op.getOperand(3); ISD::CondCode CC = cast(Op.getOperand(4))->get(); SDLoc DL(Op); NegateCC(LHS, RHS, CC); SDValue TargetCC = DAG.getConstant(CC, DL, MVT::i64); SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); SDValue Ops[] = {LHS, RHS, TargetCC, TrueV, FalseV}; return DAG.getNode(BPFISD::SELECT_CC, DL, VTs, Ops); } const char *BPFTargetLowering::getTargetNodeName(unsigned Opcode) const { switch ((BPFISD::NodeType)Opcode) { case BPFISD::FIRST_NUMBER: break; case BPFISD::RET_FLAG: return "BPFISD::RET_FLAG"; case BPFISD::CALL: return "BPFISD::CALL"; case BPFISD::SELECT_CC: return "BPFISD::SELECT_CC"; case BPFISD::BR_CC: return "BPFISD::BR_CC"; case BPFISD::Wrapper: return "BPFISD::Wrapper"; } return nullptr; } SDValue BPFTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { auto N = cast(Op); assert(N->getOffset() == 0 && "Invalid offset for global address"); SDLoc DL(Op); const GlobalValue *GV = N->getGlobal(); SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i64); return DAG.getNode(BPFISD::Wrapper, DL, MVT::i64, GA); } MachineBasicBlock * BPFTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const { const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo(); DebugLoc DL = MI.getDebugLoc(); bool isSelectOp = MI.getOpcode() == BPF::Select; assert((isSelectOp || MI.getOpcode() == BPF::Select_Ri) && "Unexpected instr type to insert"); // To "insert" a SELECT instruction, we actually have to insert the diamond // control-flow pattern. The incoming instruction knows the destination vreg // to set, the condition code register to branch on, the true/false values to // select between, and a branch opcode to use. const BasicBlock *LLVM_BB = BB->getBasicBlock(); MachineFunction::iterator I = ++BB->getIterator(); // ThisMBB: // ... // TrueVal = ... // jmp_XX r1, r2 goto Copy1MBB // fallthrough --> Copy0MBB MachineBasicBlock *ThisMBB = BB; MachineFunction *F = BB->getParent(); MachineBasicBlock *Copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *Copy1MBB = F->CreateMachineBasicBlock(LLVM_BB); F->insert(I, Copy0MBB); F->insert(I, Copy1MBB); // Update machine-CFG edges by transferring all successors of the current // block to the new block which will contain the Phi node for the select. Copy1MBB->splice(Copy1MBB->begin(), BB, std::next(MachineBasicBlock::iterator(MI)), BB->end()); Copy1MBB->transferSuccessorsAndUpdatePHIs(BB); // Next, add the true and fallthrough blocks as its successors. BB->addSuccessor(Copy0MBB); BB->addSuccessor(Copy1MBB); // Insert Branch if Flag unsigned LHS = MI.getOperand(1).getReg(); int CC = MI.getOperand(3).getImm(); int NewCC; switch (CC) { case ISD::SETGT: NewCC = isSelectOp ? BPF::JSGT_rr : BPF::JSGT_ri; break; case ISD::SETUGT: NewCC = isSelectOp ? BPF::JUGT_rr : BPF::JUGT_ri; break; case ISD::SETGE: NewCC = isSelectOp ? BPF::JSGE_rr : BPF::JSGE_ri; break; case ISD::SETUGE: NewCC = isSelectOp ? BPF::JUGE_rr : BPF::JUGE_ri; break; case ISD::SETEQ: NewCC = isSelectOp ? BPF::JEQ_rr : BPF::JEQ_ri; break; case ISD::SETNE: NewCC = isSelectOp ? BPF::JNE_rr : BPF::JNE_ri; break; default: report_fatal_error("unimplemented select CondCode " + Twine(CC)); } if (isSelectOp) BuildMI(BB, DL, TII.get(NewCC)) .addReg(LHS) .addReg(MI.getOperand(2).getReg()) .addMBB(Copy1MBB); - else + else { + int64_t imm32 = MI.getOperand(2).getImm(); + // sanity check before we build J*_ri instruction. + assert (isInt<32>(imm32)); BuildMI(BB, DL, TII.get(NewCC)) .addReg(LHS) - .addImm(MI.getOperand(2).getImm()) + .addImm(imm32) .addMBB(Copy1MBB); + } // Copy0MBB: // %FalseValue = ... // # fallthrough to Copy1MBB BB = Copy0MBB; // Update machine-CFG edges BB->addSuccessor(Copy1MBB); // Copy1MBB: // %Result = phi [ %FalseValue, Copy0MBB ], [ %TrueValue, ThisMBB ] // ... BB = Copy1MBB; BuildMI(*BB, BB->begin(), DL, TII.get(BPF::PHI), MI.getOperand(0).getReg()) .addReg(MI.getOperand(5).getReg()) .addMBB(Copy0MBB) .addReg(MI.getOperand(4).getReg()) .addMBB(ThisMBB); MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } Index: head/contrib/llvm/lib/Target/BPF/BPFInstrInfo.td =================================================================== --- head/contrib/llvm/lib/Target/BPF/BPFInstrInfo.td (revision 326908) +++ head/contrib/llvm/lib/Target/BPF/BPFInstrInfo.td (revision 326909) @@ -1,585 +1,585 @@ //===-- BPFInstrInfo.td - Target Description for BPF Target ---------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file describes the BPF instructions in TableGen format. // //===----------------------------------------------------------------------===// include "BPFInstrFormats.td" // Instruction Operands and Patterns // These are target-independent nodes, but have target-specific formats. def SDT_BPFCallSeqStart : SDCallSeqStart<[SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>; def SDT_BPFCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>; def SDT_BPFCall : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; def SDT_BPFSetFlag : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>]>; def SDT_BPFSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>, SDTCisSameAs<0, 4>, SDTCisSameAs<4, 5>]>; def SDT_BPFBrCC : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>, SDTCisVT<3, OtherVT>]>; def SDT_BPFWrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; def BPFcall : SDNode<"BPFISD::CALL", SDT_BPFCall, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>; def BPFretflag : SDNode<"BPFISD::RET_FLAG", SDTNone, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; def BPFcallseq_start: SDNode<"ISD::CALLSEQ_START", SDT_BPFCallSeqStart, [SDNPHasChain, SDNPOutGlue]>; def BPFcallseq_end : SDNode<"ISD::CALLSEQ_END", SDT_BPFCallSeqEnd, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; def BPFbrcc : SDNode<"BPFISD::BR_CC", SDT_BPFBrCC, [SDNPHasChain, SDNPOutGlue, SDNPInGlue]>; def BPFselectcc : SDNode<"BPFISD::SELECT_CC", SDT_BPFSelectCC, [SDNPInGlue]>; def BPFWrapper : SDNode<"BPFISD::Wrapper", SDT_BPFWrapper>; def brtarget : Operand; def calltarget : Operand; def u64imm : Operand { let PrintMethod = "printImm64Operand"; } def i64immSExt32 : PatLeaf<(i64 imm), [{return isInt<32>(N->getSExtValue()); }]>; // Addressing modes. def ADDRri : ComplexPattern; def FIri : ComplexPattern; // Address operands def MEMri : Operand { let PrintMethod = "printMemOperand"; let EncoderMethod = "getMemoryOpValue"; let DecoderMethod = "decodeMemoryOpValue"; let MIOperandInfo = (ops GPR, i16imm); } // Conditional code predicates - used for pattern matching for jump instructions def BPF_CC_EQ : PatLeaf<(i64 imm), [{return (N->getZExtValue() == ISD::SETEQ);}]>; def BPF_CC_NE : PatLeaf<(i64 imm), [{return (N->getZExtValue() == ISD::SETNE);}]>; def BPF_CC_GE : PatLeaf<(i64 imm), [{return (N->getZExtValue() == ISD::SETGE);}]>; def BPF_CC_GT : PatLeaf<(i64 imm), [{return (N->getZExtValue() == ISD::SETGT);}]>; def BPF_CC_GTU : PatLeaf<(i64 imm), [{return (N->getZExtValue() == ISD::SETUGT);}]>; def BPF_CC_GEU : PatLeaf<(i64 imm), [{return (N->getZExtValue() == ISD::SETUGE);}]>; // jump instructions class JMP_RR Opc, string OpcodeStr, PatLeaf Cond> : InstBPF<(outs), (ins GPR:$dst, GPR:$src, brtarget:$BrDst), "if $dst "#OpcodeStr#" $src goto $BrDst", [(BPFbrcc i64:$dst, i64:$src, Cond, bb:$BrDst)]> { bits<4> op; bits<1> BPFSrc; bits<4> dst; bits<4> src; bits<16> BrDst; let Inst{63-60} = op; let Inst{59} = BPFSrc; let Inst{55-52} = src; let Inst{51-48} = dst; let Inst{47-32} = BrDst; let op = Opc; let BPFSrc = 1; let BPFClass = 5; // BPF_JMP } class JMP_RI Opc, string OpcodeStr, PatLeaf Cond> : InstBPF<(outs), (ins GPR:$dst, i64imm:$imm, brtarget:$BrDst), "if $dst "#OpcodeStr#" $imm goto $BrDst", [(BPFbrcc i64:$dst, i64immSExt32:$imm, Cond, bb:$BrDst)]> { bits<4> op; bits<1> BPFSrc; bits<4> dst; bits<16> BrDst; bits<32> imm; let Inst{63-60} = op; let Inst{59} = BPFSrc; let Inst{51-48} = dst; let Inst{47-32} = BrDst; let Inst{31-0} = imm; let op = Opc; let BPFSrc = 0; let BPFClass = 5; // BPF_JMP } multiclass J Opc, string OpcodeStr, PatLeaf Cond> { def _rr : JMP_RR; def _ri : JMP_RI; } let isBranch = 1, isTerminator = 1, hasDelaySlot=0 in { // cmp+goto instructions defm JEQ : J<0x1, "==", BPF_CC_EQ>; defm JUGT : J<0x2, ">", BPF_CC_GTU>; defm JUGE : J<0x3, ">=", BPF_CC_GEU>; defm JNE : J<0x5, "!=", BPF_CC_NE>; defm JSGT : J<0x6, "s>", BPF_CC_GT>; defm JSGE : J<0x7, "s>=", BPF_CC_GE>; } // ALU instructions class ALU_RI Opc, string OpcodeStr, SDNode OpNode> : InstBPF<(outs GPR:$dst), (ins GPR:$src2, i64imm:$imm), "$dst "#OpcodeStr#" $imm", [(set GPR:$dst, (OpNode GPR:$src2, i64immSExt32:$imm))]> { bits<4> op; bits<1> BPFSrc; bits<4> dst; bits<32> imm; let Inst{63-60} = op; let Inst{59} = BPFSrc; let Inst{51-48} = dst; let Inst{31-0} = imm; let op = Opc; let BPFSrc = 0; let BPFClass = 7; // BPF_ALU64 } class ALU_RR Opc, string OpcodeStr, SDNode OpNode> : InstBPF<(outs GPR:$dst), (ins GPR:$src2, GPR:$src), "$dst "#OpcodeStr#" $src", [(set GPR:$dst, (OpNode i64:$src2, i64:$src))]> { bits<4> op; bits<1> BPFSrc; bits<4> dst; bits<4> src; let Inst{63-60} = op; let Inst{59} = BPFSrc; let Inst{55-52} = src; let Inst{51-48} = dst; let op = Opc; let BPFSrc = 1; let BPFClass = 7; // BPF_ALU64 } multiclass ALU Opc, string OpcodeStr, SDNode OpNode> { def _rr : ALU_RR; def _ri : ALU_RI; } let Constraints = "$dst = $src2" in { let isAsCheapAsAMove = 1 in { defm ADD : ALU<0x0, "+=", add>; defm SUB : ALU<0x1, "-=", sub>; defm OR : ALU<0x4, "|=", or>; defm AND : ALU<0x5, "&=", and>; defm SLL : ALU<0x6, "<<=", shl>; defm SRL : ALU<0x7, ">>=", srl>; defm XOR : ALU<0xa, "^=", xor>; defm SRA : ALU<0xc, "s>>=", sra>; } defm MUL : ALU<0x2, "*=", mul>; defm DIV : ALU<0x3, "/=", udiv>; } class MOV_RR : InstBPF<(outs GPR:$dst), (ins GPR:$src), "$dst "#OpcodeStr#" $src", []> { bits<4> op; bits<1> BPFSrc; bits<4> dst; bits<4> src; let Inst{63-60} = op; let Inst{59} = BPFSrc; let Inst{55-52} = src; let Inst{51-48} = dst; let op = 0xb; // BPF_MOV let BPFSrc = 1; // BPF_X let BPFClass = 7; // BPF_ALU64 } class MOV_RI : InstBPF<(outs GPR:$dst), (ins i64imm:$imm), "$dst "#OpcodeStr#" $imm", [(set GPR:$dst, (i64 i64immSExt32:$imm))]> { bits<4> op; bits<1> BPFSrc; bits<4> dst; bits<32> imm; let Inst{63-60} = op; let Inst{59} = BPFSrc; let Inst{51-48} = dst; let Inst{31-0} = imm; let op = 0xb; // BPF_MOV let BPFSrc = 0; // BPF_K let BPFClass = 7; // BPF_ALU64 } class LD_IMM64 Pseudo, string OpcodeStr> : InstBPF<(outs GPR:$dst), (ins u64imm:$imm), "$dst "#OpcodeStr#" ${imm}ll", [(set GPR:$dst, (i64 imm:$imm))]> { bits<3> mode; bits<2> size; bits<4> dst; bits<64> imm; let Inst{63-61} = mode; let Inst{60-59} = size; let Inst{51-48} = dst; let Inst{55-52} = Pseudo; let Inst{47-32} = 0; let Inst{31-0} = imm{31-0}; let mode = 0; // BPF_IMM let size = 3; // BPF_DW let BPFClass = 0; // BPF_LD } let isReMaterializable = 1, isAsCheapAsAMove = 1 in { def LD_imm64 : LD_IMM64<0, "=">; def MOV_rr : MOV_RR<"=">; def MOV_ri : MOV_RI<"=">; } def FI_ri : InstBPF<(outs GPR:$dst), (ins MEMri:$addr), "lea\t$dst, $addr", [(set i64:$dst, FIri:$addr)]> { // This is a tentative instruction, and will be replaced // with MOV_rr and ADD_ri in PEI phase let Inst{63-61} = 0; let Inst{60-59} = 3; let Inst{51-48} = 0; let Inst{55-52} = 2; let Inst{47-32} = 0; let Inst{31-0} = 0; let BPFClass = 0; } def LD_pseudo : InstBPF<(outs GPR:$dst), (ins i64imm:$pseudo, u64imm:$imm), "ld_pseudo\t$dst, $pseudo, $imm", [(set GPR:$dst, (int_bpf_pseudo imm:$pseudo, imm:$imm))]> { bits<3> mode; bits<2> size; bits<4> dst; bits<64> imm; bits<4> pseudo; let Inst{63-61} = mode; let Inst{60-59} = size; let Inst{51-48} = dst; let Inst{55-52} = pseudo; let Inst{47-32} = 0; let Inst{31-0} = imm{31-0}; let mode = 0; // BPF_IMM let size = 3; // BPF_DW let BPFClass = 0; // BPF_LD } // STORE instructions class STORE SizeOp, string OpcodeStr, list Pattern> : InstBPF<(outs), (ins GPR:$src, MEMri:$addr), "*("#OpcodeStr#" *)($addr) = $src", Pattern> { bits<3> mode; bits<2> size; bits<4> src; bits<20> addr; let Inst{63-61} = mode; let Inst{60-59} = size; let Inst{51-48} = addr{19-16}; // base reg let Inst{55-52} = src; let Inst{47-32} = addr{15-0}; // offset let mode = 3; // BPF_MEM let size = SizeOp; let BPFClass = 3; // BPF_STX } class STOREi64 Opc, string OpcodeStr, PatFrag OpNode> : STORE; def STW : STOREi64<0x0, "u32", truncstorei32>; def STH : STOREi64<0x1, "u16", truncstorei16>; def STB : STOREi64<0x2, "u8", truncstorei8>; def STD : STOREi64<0x3, "u64", store>; // LOAD instructions class LOAD SizeOp, string OpcodeStr, list Pattern> : InstBPF<(outs GPR:$dst), (ins MEMri:$addr), "$dst = *("#OpcodeStr#" *)($addr)", Pattern> { bits<3> mode; bits<2> size; bits<4> dst; bits<20> addr; let Inst{63-61} = mode; let Inst{60-59} = size; let Inst{51-48} = dst; let Inst{55-52} = addr{19-16}; let Inst{47-32} = addr{15-0}; let mode = 3; // BPF_MEM let size = SizeOp; let BPFClass = 1; // BPF_LDX } class LOADi64 SizeOp, string OpcodeStr, PatFrag OpNode> : LOAD; def LDW : LOADi64<0x0, "u32", zextloadi32>; def LDH : LOADi64<0x1, "u16", zextloadi16>; def LDB : LOADi64<0x2, "u8", zextloadi8>; def LDD : LOADi64<0x3, "u64", load>; class BRANCH Opc, string OpcodeStr, list Pattern> : InstBPF<(outs), (ins brtarget:$BrDst), !strconcat(OpcodeStr, " $BrDst"), Pattern> { bits<4> op; bits<16> BrDst; bits<1> BPFSrc; let Inst{63-60} = op; let Inst{59} = BPFSrc; let Inst{47-32} = BrDst; let op = Opc; let BPFSrc = 0; let BPFClass = 5; // BPF_JMP } class CALL : InstBPF<(outs), (ins calltarget:$BrDst), !strconcat(OpcodeStr, " $BrDst"), []> { bits<4> op; bits<32> BrDst; bits<1> BPFSrc; let Inst{63-60} = op; let Inst{59} = BPFSrc; let Inst{31-0} = BrDst; let op = 8; // BPF_CALL let BPFSrc = 0; let BPFClass = 5; // BPF_JMP } // Jump always let isBranch = 1, isTerminator = 1, hasDelaySlot=0, isBarrier = 1 in { def JMP : BRANCH<0x0, "goto", [(br bb:$BrDst)]>; } // Jump and link let isCall=1, hasDelaySlot=0, Uses = [R11], // Potentially clobbered registers Defs = [R0, R1, R2, R3, R4, R5] in { def JAL : CALL<"call">; } class NOP_I : InstBPF<(outs), (ins i32imm:$imm), !strconcat(OpcodeStr, "\t$imm"), []> { // mov r0, r0 == nop bits<4> op; bits<1> BPFSrc; bits<4> dst; bits<4> src; let Inst{63-60} = op; let Inst{59} = BPFSrc; let Inst{55-52} = src; let Inst{51-48} = dst; let op = 0xb; // BPF_MOV let BPFSrc = 1; // BPF_X let BPFClass = 7; // BPF_ALU64 let src = 0; // R0 let dst = 0; // R0 } let hasSideEffects = 0 in def NOP : NOP_I<"nop">; class RET : InstBPF<(outs), (ins), !strconcat(OpcodeStr, ""), [(BPFretflag)]> { bits<4> op; let Inst{63-60} = op; let Inst{59} = 0; let Inst{31-0} = 0; let op = 9; // BPF_EXIT let BPFClass = 5; // BPF_JMP } let isReturn = 1, isTerminator = 1, hasDelaySlot=0, isBarrier = 1, isNotDuplicable = 1 in { def RET : RET<"exit">; } // ADJCALLSTACKDOWN/UP pseudo insns let Defs = [R11], Uses = [R11] in { def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2), "#ADJCALLSTACKDOWN $amt1 $amt2", [(BPFcallseq_start timm:$amt1, timm:$amt2)]>; def ADJCALLSTACKUP : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2), "#ADJCALLSTACKUP $amt1 $amt2", [(BPFcallseq_end timm:$amt1, timm:$amt2)]>; } let usesCustomInserter = 1 in { def Select : Pseudo<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs, i64imm:$imm, GPR:$src, GPR:$src2), "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2", [(set i64:$dst, (BPFselectcc i64:$lhs, i64:$rhs, (i64 imm:$imm), i64:$src, i64:$src2))]>; def Select_Ri : Pseudo<(outs GPR:$dst), (ins GPR:$lhs, i64imm:$rhs, i64imm:$imm, GPR:$src, GPR:$src2), "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2", [(set i64:$dst, - (BPFselectcc i64:$lhs, (i64 imm:$rhs), (i64 imm:$imm), i64:$src, i64:$src2))]>; + (BPFselectcc i64:$lhs, (i64 i64immSExt32:$rhs), (i64 imm:$imm), i64:$src, i64:$src2))]>; } // load 64-bit global addr into register def : Pat<(BPFWrapper tglobaladdr:$in), (LD_imm64 tglobaladdr:$in)>; // 0xffffFFFF doesn't fit into simm32, optimize common case def : Pat<(i64 (and (i64 GPR:$src), 0xffffFFFF)), (SRL_ri (SLL_ri (i64 GPR:$src), 32), 32)>; // Calls def : Pat<(BPFcall tglobaladdr:$dst), (JAL tglobaladdr:$dst)>; def : Pat<(BPFcall texternalsym:$dst), (JAL texternalsym:$dst)>; def : Pat<(BPFcall imm:$dst), (JAL imm:$dst)>; // Loads def : Pat<(extloadi8 ADDRri:$src), (i64 (LDB ADDRri:$src))>; def : Pat<(extloadi16 ADDRri:$src), (i64 (LDH ADDRri:$src))>; def : Pat<(extloadi32 ADDRri:$src), (i64 (LDW ADDRri:$src))>; // Atomics class XADD SizeOp, string OpcodeStr, PatFrag OpNode> : InstBPF<(outs GPR:$dst), (ins MEMri:$addr, GPR:$val), "lock *("#OpcodeStr#" *)($addr) += $val", [(set GPR:$dst, (OpNode ADDRri:$addr, GPR:$val))]> { bits<3> mode; bits<2> size; bits<4> dst; bits<20> addr; let Inst{63-61} = mode; let Inst{60-59} = size; let Inst{51-48} = addr{19-16}; // base reg let Inst{55-52} = dst; let Inst{47-32} = addr{15-0}; // offset let mode = 6; // BPF_XADD let size = SizeOp; let BPFClass = 3; // BPF_STX } let Constraints = "$dst = $val" in { def XADD32 : XADD<0, "u32", atomic_load_add_32>; def XADD64 : XADD<3, "u64", atomic_load_add_64>; // undefined def XADD16 : XADD<1, "xadd16", atomic_load_add_16>; // undefined def XADD8 : XADD<2, "xadd8", atomic_load_add_8>; } // bswap16, bswap32, bswap64 class BSWAP SizeOp, string OpcodeStr, list Pattern> : InstBPF<(outs GPR:$dst), (ins GPR:$src), !strconcat(OpcodeStr, "\t$dst"), Pattern> { bits<4> op; bits<1> BPFSrc; bits<4> dst; bits<32> imm; let Inst{63-60} = op; let Inst{59} = BPFSrc; let Inst{51-48} = dst; let Inst{31-0} = imm; let op = 0xd; // BPF_END let BPFSrc = 1; // BPF_TO_BE (TODO: use BPF_TO_LE for big-endian target) let BPFClass = 4; // BPF_ALU let imm = SizeOp; } let Constraints = "$dst = $src" in { def BSWAP16 : BSWAP<16, "bswap16", [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>; def BSWAP32 : BSWAP<32, "bswap32", [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>; def BSWAP64 : BSWAP<64, "bswap64", [(set GPR:$dst, (bswap GPR:$src))]>; } let Defs = [R0, R1, R2, R3, R4, R5], Uses = [R6], hasSideEffects = 1, hasExtraDefRegAllocReq = 1, hasExtraSrcRegAllocReq = 1, mayLoad = 1 in { class LOAD_ABS SizeOp, string OpcodeStr, Intrinsic OpNode> : InstBPF<(outs), (ins GPR:$skb, i64imm:$imm), "r0 = *("#OpcodeStr#" *)skb[$imm]", [(set R0, (OpNode GPR:$skb, i64immSExt32:$imm))]> { bits<3> mode; bits<2> size; bits<32> imm; let Inst{63-61} = mode; let Inst{60-59} = size; let Inst{31-0} = imm; let mode = 1; // BPF_ABS let size = SizeOp; let BPFClass = 0; // BPF_LD } class LOAD_IND SizeOp, string OpcodeStr, Intrinsic OpNode> : InstBPF<(outs), (ins GPR:$skb, GPR:$val), "r0 = *("#OpcodeStr#" *)skb[$val]", [(set R0, (OpNode GPR:$skb, GPR:$val))]> { bits<3> mode; bits<2> size; bits<4> val; let Inst{63-61} = mode; let Inst{60-59} = size; let Inst{55-52} = val; let mode = 2; // BPF_IND let size = SizeOp; let BPFClass = 0; // BPF_LD } } def LD_ABS_B : LOAD_ABS<2, "u8", int_bpf_load_byte>; def LD_ABS_H : LOAD_ABS<1, "u16", int_bpf_load_half>; def LD_ABS_W : LOAD_ABS<0, "u32", int_bpf_load_word>; def LD_IND_B : LOAD_IND<2, "u8", int_bpf_load_byte>; def LD_IND_H : LOAD_IND<1, "u16", int_bpf_load_half>; def LD_IND_W : LOAD_IND<0, "u32", int_bpf_load_word>; Index: head/contrib/llvm/lib/Transforms/Scalar/NewGVN.cpp =================================================================== --- head/contrib/llvm/lib/Transforms/Scalar/NewGVN.cpp (revision 326908) +++ head/contrib/llvm/lib/Transforms/Scalar/NewGVN.cpp (revision 326909) @@ -1,3941 +1,3943 @@ //===---- NewGVN.cpp - Global Value Numbering Pass --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// \file /// This file implements the new LLVM's Global Value Numbering pass. /// GVN partitions values computed by a function into congruence classes. /// Values ending up in the same congruence class are guaranteed to be the same /// for every execution of the program. In that respect, congruency is a /// compile-time approximation of equivalence of values at runtime. /// The algorithm implemented here uses a sparse formulation and it's based /// on the ideas described in the paper: /// "A Sparse Algorithm for Predicated Global Value Numbering" from /// Karthik Gargi. /// /// A brief overview of the algorithm: The algorithm is essentially the same as /// the standard RPO value numbering algorithm (a good reference is the paper /// "SCC based value numbering" by L. Taylor Simpson) with one major difference: /// The RPO algorithm proceeds, on every iteration, to process every reachable /// block and every instruction in that block. This is because the standard RPO /// algorithm does not track what things have the same value number, it only /// tracks what the value number of a given operation is (the mapping is /// operation -> value number). Thus, when a value number of an operation /// changes, it must reprocess everything to ensure all uses of a value number /// get updated properly. In constrast, the sparse algorithm we use *also* /// tracks what operations have a given value number (IE it also tracks the /// reverse mapping from value number -> operations with that value number), so /// that it only needs to reprocess the instructions that are affected when /// something's value number changes. The vast majority of complexity and code /// in this file is devoted to tracking what value numbers could change for what /// instructions when various things happen. The rest of the algorithm is /// devoted to performing symbolic evaluation, forward propagation, and /// simplification of operations based on the value numbers deduced so far /// /// In order to make the GVN mostly-complete, we use a technique derived from /// "Detection of Redundant Expressions: A Complete and Polynomial-time /// Algorithm in SSA" by R.R. Pai. The source of incompleteness in most SSA /// based GVN algorithms is related to their inability to detect equivalence /// between phi of ops (IE phi(a+b, c+d)) and op of phis (phi(a,c) + phi(b, d)). /// We resolve this issue by generating the equivalent "phi of ops" form for /// each op of phis we see, in a way that only takes polynomial time to resolve. /// /// We also do not perform elimination by using any published algorithm. All /// published algorithms are O(Instructions). Instead, we use a technique that /// is O(number of operations with the same value number), enabling us to skip /// trying to eliminate things that have unique value numbers. //===----------------------------------------------------------------------===// #include "llvm/Transforms/Scalar/NewGVN.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/CFG.h" #include "llvm/Analysis/CFGPrinter.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/MemoryBuiltins.h" #include "llvm/Analysis/MemoryLocation.h" #include "llvm/Analysis/MemorySSA.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/PatternMatch.h" #include "llvm/IR/Type.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/DebugCounter.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar/GVNExpression.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/PredicateInfo.h" #include "llvm/Transforms/Utils/VNCoercion.h" #include #include #include #include using namespace llvm; using namespace PatternMatch; using namespace llvm::GVNExpression; using namespace llvm::VNCoercion; #define DEBUG_TYPE "newgvn" STATISTIC(NumGVNInstrDeleted, "Number of instructions deleted"); STATISTIC(NumGVNBlocksDeleted, "Number of blocks deleted"); STATISTIC(NumGVNOpsSimplified, "Number of Expressions simplified"); STATISTIC(NumGVNPhisAllSame, "Number of PHIs whos arguments are all the same"); STATISTIC(NumGVNMaxIterations, "Maximum Number of iterations it took to converge GVN"); STATISTIC(NumGVNLeaderChanges, "Number of leader changes"); STATISTIC(NumGVNSortedLeaderChanges, "Number of sorted leader changes"); STATISTIC(NumGVNAvoidedSortedLeaderChanges, "Number of avoided sorted leader changes"); STATISTIC(NumGVNDeadStores, "Number of redundant/dead stores eliminated"); STATISTIC(NumGVNPHIOfOpsCreated, "Number of PHI of ops created"); STATISTIC(NumGVNPHIOfOpsEliminations, "Number of things eliminated using PHI of ops"); DEBUG_COUNTER(VNCounter, "newgvn-vn", "Controls which instructions are value numbered") DEBUG_COUNTER(PHIOfOpsCounter, "newgvn-phi", "Controls which instructions we create phi of ops for") // Currently store defining access refinement is too slow due to basicaa being // egregiously slow. This flag lets us keep it working while we work on this // issue. static cl::opt EnableStoreRefinement("enable-store-refinement", cl::init(false), cl::Hidden); //===----------------------------------------------------------------------===// // GVN Pass //===----------------------------------------------------------------------===// // Anchor methods. namespace llvm { namespace GVNExpression { Expression::~Expression() = default; BasicExpression::~BasicExpression() = default; CallExpression::~CallExpression() = default; LoadExpression::~LoadExpression() = default; StoreExpression::~StoreExpression() = default; AggregateValueExpression::~AggregateValueExpression() = default; PHIExpression::~PHIExpression() = default; } } // Tarjan's SCC finding algorithm with Nuutila's improvements // SCCIterator is actually fairly complex for the simple thing we want. // It also wants to hand us SCC's that are unrelated to the phi node we ask // about, and have us process them there or risk redoing work. // Graph traits over a filter iterator also doesn't work that well here. // This SCC finder is specialized to walk use-def chains, and only follows // instructions, // not generic values (arguments, etc). struct TarjanSCC { TarjanSCC() : Components(1) {} void Start(const Instruction *Start) { if (Root.lookup(Start) == 0) FindSCC(Start); } const SmallPtrSetImpl &getComponentFor(const Value *V) const { unsigned ComponentID = ValueToComponent.lookup(V); assert(ComponentID > 0 && "Asking for a component for a value we never processed"); return Components[ComponentID]; } private: void FindSCC(const Instruction *I) { Root[I] = ++DFSNum; // Store the DFS Number we had before it possibly gets incremented. unsigned int OurDFS = DFSNum; for (auto &Op : I->operands()) { if (auto *InstOp = dyn_cast(Op)) { if (Root.lookup(Op) == 0) FindSCC(InstOp); if (!InComponent.count(Op)) Root[I] = std::min(Root.lookup(I), Root.lookup(Op)); } } // See if we really were the root of a component, by seeing if we still have // our DFSNumber. If we do, we are the root of the component, and we have // completed a component. If we do not, we are not the root of a component, // and belong on the component stack. if (Root.lookup(I) == OurDFS) { unsigned ComponentID = Components.size(); Components.resize(Components.size() + 1); auto &Component = Components.back(); Component.insert(I); DEBUG(dbgs() << "Component root is " << *I << "\n"); InComponent.insert(I); ValueToComponent[I] = ComponentID; // Pop a component off the stack and label it. while (!Stack.empty() && Root.lookup(Stack.back()) >= OurDFS) { auto *Member = Stack.back(); DEBUG(dbgs() << "Component member is " << *Member << "\n"); Component.insert(Member); InComponent.insert(Member); ValueToComponent[Member] = ComponentID; Stack.pop_back(); } } else { // Part of a component, push to stack Stack.push_back(I); } } unsigned int DFSNum = 1; SmallPtrSet InComponent; DenseMap Root; SmallVector Stack; // Store the components as vector of ptr sets, because we need the topo order // of SCC's, but not individual member order SmallVector, 8> Components; DenseMap ValueToComponent; }; // Congruence classes represent the set of expressions/instructions // that are all the same *during some scope in the function*. // That is, because of the way we perform equality propagation, and // because of memory value numbering, it is not correct to assume // you can willy-nilly replace any member with any other at any // point in the function. // // For any Value in the Member set, it is valid to replace any dominated member // with that Value. // // Every congruence class has a leader, and the leader is used to symbolize // instructions in a canonical way (IE every operand of an instruction that is a // member of the same congruence class will always be replaced with leader // during symbolization). To simplify symbolization, we keep the leader as a // constant if class can be proved to be a constant value. Otherwise, the // leader is the member of the value set with the smallest DFS number. Each // congruence class also has a defining expression, though the expression may be // null. If it exists, it can be used for forward propagation and reassociation // of values. // For memory, we also track a representative MemoryAccess, and a set of memory // members for MemoryPhis (which have no real instructions). Note that for // memory, it seems tempting to try to split the memory members into a // MemoryCongruenceClass or something. Unfortunately, this does not work // easily. The value numbering of a given memory expression depends on the // leader of the memory congruence class, and the leader of memory congruence // class depends on the value numbering of a given memory expression. This // leads to wasted propagation, and in some cases, missed optimization. For // example: If we had value numbered two stores together before, but now do not, // we move them to a new value congruence class. This in turn will move at one // of the memorydefs to a new memory congruence class. Which in turn, affects // the value numbering of the stores we just value numbered (because the memory // congruence class is part of the value number). So while theoretically // possible to split them up, it turns out to be *incredibly* complicated to get // it to work right, because of the interdependency. While structurally // slightly messier, it is algorithmically much simpler and faster to do what we // do here, and track them both at once in the same class. // Note: The default iterators for this class iterate over values class CongruenceClass { public: using MemberType = Value; using MemberSet = SmallPtrSet; using MemoryMemberType = MemoryPhi; using MemoryMemberSet = SmallPtrSet; explicit CongruenceClass(unsigned ID) : ID(ID) {} CongruenceClass(unsigned ID, Value *Leader, const Expression *E) : ID(ID), RepLeader(Leader), DefiningExpr(E) {} unsigned getID() const { return ID; } // True if this class has no members left. This is mainly used for assertion // purposes, and for skipping empty classes. bool isDead() const { // If it's both dead from a value perspective, and dead from a memory // perspective, it's really dead. return empty() && memory_empty(); } // Leader functions Value *getLeader() const { return RepLeader; } void setLeader(Value *Leader) { RepLeader = Leader; } const std::pair &getNextLeader() const { return NextLeader; } void resetNextLeader() { NextLeader = {nullptr, ~0}; } void addPossibleNextLeader(std::pair LeaderPair) { if (LeaderPair.second < NextLeader.second) NextLeader = LeaderPair; } Value *getStoredValue() const { return RepStoredValue; } void setStoredValue(Value *Leader) { RepStoredValue = Leader; } const MemoryAccess *getMemoryLeader() const { return RepMemoryAccess; } void setMemoryLeader(const MemoryAccess *Leader) { RepMemoryAccess = Leader; } // Forward propagation info const Expression *getDefiningExpr() const { return DefiningExpr; } // Value member set bool empty() const { return Members.empty(); } unsigned size() const { return Members.size(); } MemberSet::const_iterator begin() const { return Members.begin(); } MemberSet::const_iterator end() const { return Members.end(); } void insert(MemberType *M) { Members.insert(M); } void erase(MemberType *M) { Members.erase(M); } void swap(MemberSet &Other) { Members.swap(Other); } // Memory member set bool memory_empty() const { return MemoryMembers.empty(); } unsigned memory_size() const { return MemoryMembers.size(); } MemoryMemberSet::const_iterator memory_begin() const { return MemoryMembers.begin(); } MemoryMemberSet::const_iterator memory_end() const { return MemoryMembers.end(); } iterator_range memory() const { return make_range(memory_begin(), memory_end()); } void memory_insert(const MemoryMemberType *M) { MemoryMembers.insert(M); } void memory_erase(const MemoryMemberType *M) { MemoryMembers.erase(M); } // Store count unsigned getStoreCount() const { return StoreCount; } void incStoreCount() { ++StoreCount; } void decStoreCount() { assert(StoreCount != 0 && "Store count went negative"); --StoreCount; } // True if this class has no memory members. bool definesNoMemory() const { return StoreCount == 0 && memory_empty(); } // Return true if two congruence classes are equivalent to each other. This // means // that every field but the ID number and the dead field are equivalent. bool isEquivalentTo(const CongruenceClass *Other) const { if (!Other) return false; if (this == Other) return true; if (std::tie(StoreCount, RepLeader, RepStoredValue, RepMemoryAccess) != std::tie(Other->StoreCount, Other->RepLeader, Other->RepStoredValue, Other->RepMemoryAccess)) return false; if (DefiningExpr != Other->DefiningExpr) if (!DefiningExpr || !Other->DefiningExpr || *DefiningExpr != *Other->DefiningExpr) return false; // We need some ordered set std::set AMembers(Members.begin(), Members.end()); std::set BMembers(Members.begin(), Members.end()); return AMembers == BMembers; } private: unsigned ID; // Representative leader. Value *RepLeader = nullptr; // The most dominating leader after our current leader, because the member set // is not sorted and is expensive to keep sorted all the time. std::pair NextLeader = {nullptr, ~0U}; // If this is represented by a store, the value of the store. Value *RepStoredValue = nullptr; // If this class contains MemoryDefs or MemoryPhis, this is the leading memory // access. const MemoryAccess *RepMemoryAccess = nullptr; // Defining Expression. const Expression *DefiningExpr = nullptr; // Actual members of this class. MemberSet Members; // This is the set of MemoryPhis that exist in the class. MemoryDefs and // MemoryUses have real instructions representing them, so we only need to // track MemoryPhis here. MemoryMemberSet MemoryMembers; // Number of stores in this congruence class. // This is used so we can detect store equivalence changes properly. int StoreCount = 0; }; namespace llvm { struct ExactEqualsExpression { const Expression &E; explicit ExactEqualsExpression(const Expression &E) : E(E) {} hash_code getComputedHash() const { return E.getComputedHash(); } bool operator==(const Expression &Other) const { return E.exactlyEquals(Other); } }; template <> struct DenseMapInfo { static const Expression *getEmptyKey() { auto Val = static_cast(-1); Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; return reinterpret_cast(Val); } static const Expression *getTombstoneKey() { auto Val = static_cast(~1U); Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; return reinterpret_cast(Val); } static unsigned getHashValue(const Expression *E) { return E->getComputedHash(); } static unsigned getHashValue(const ExactEqualsExpression &E) { return E.getComputedHash(); } static bool isEqual(const ExactEqualsExpression &LHS, const Expression *RHS) { if (RHS == getTombstoneKey() || RHS == getEmptyKey()) return false; return LHS == *RHS; } static bool isEqual(const Expression *LHS, const Expression *RHS) { if (LHS == RHS) return true; if (LHS == getTombstoneKey() || RHS == getTombstoneKey() || LHS == getEmptyKey() || RHS == getEmptyKey()) return false; // Compare hashes before equality. This is *not* what the hashtable does, // since it is computing it modulo the number of buckets, whereas we are // using the full hash keyspace. Since the hashes are precomputed, this // check is *much* faster than equality. if (LHS->getComputedHash() != RHS->getComputedHash()) return false; return *LHS == *RHS; } }; } // end namespace llvm namespace { class NewGVN { Function &F; DominatorTree *DT; const TargetLibraryInfo *TLI; AliasAnalysis *AA; MemorySSA *MSSA; MemorySSAWalker *MSSAWalker; const DataLayout &DL; std::unique_ptr PredInfo; // These are the only two things the create* functions should have // side-effects on due to allocating memory. mutable BumpPtrAllocator ExpressionAllocator; mutable ArrayRecycler ArgRecycler; mutable TarjanSCC SCCFinder; const SimplifyQuery SQ; // Number of function arguments, used by ranking unsigned int NumFuncArgs; // RPOOrdering of basic blocks DenseMap RPOOrdering; // Congruence class info. // This class is called INITIAL in the paper. It is the class everything // startsout in, and represents any value. Being an optimistic analysis, // anything in the TOP class has the value TOP, which is indeterminate and // equivalent to everything. CongruenceClass *TOPClass; std::vector CongruenceClasses; unsigned NextCongruenceNum; // Value Mappings. DenseMap ValueToClass; DenseMap ValueToExpression; // Value PHI handling, used to make equivalence between phi(op, op) and // op(phi, phi). // These mappings just store various data that would normally be part of the // IR. DenseSet PHINodeUses; // Map a temporary instruction we created to a parent block. DenseMap TempToBlock; // Map between the temporary phis we created and the real instructions they // are known equivalent to. DenseMap RealToTemp; // In order to know when we should re-process instructions that have // phi-of-ops, we track the set of expressions that they needed as // leaders. When we discover new leaders for those expressions, we process the // associated phi-of-op instructions again in case they have changed. The // other way they may change is if they had leaders, and those leaders // disappear. However, at the point they have leaders, there are uses of the // relevant operands in the created phi node, and so they will get reprocessed // through the normal user marking we perform. mutable DenseMap> AdditionalUsers; DenseMap> ExpressionToPhiOfOps; // Map from basic block to the temporary operations we created DenseMap> PHIOfOpsPHIs; // Map from temporary operation to MemoryAccess. DenseMap TempToMemory; // Set of all temporary instructions we created. DenseSet AllTempInstructions; // Mapping from predicate info we used to the instructions we used it with. // In order to correctly ensure propagation, we must keep track of what // comparisons we used, so that when the values of the comparisons change, we // propagate the information to the places we used the comparison. mutable DenseMap> PredicateToUsers; // the same reasoning as PredicateToUsers. When we skip MemoryAccesses for // stores, we no longer can rely solely on the def-use chains of MemorySSA. mutable DenseMap> MemoryToUsers; // A table storing which memorydefs/phis represent a memory state provably // equivalent to another memory state. // We could use the congruence class machinery, but the MemoryAccess's are // abstract memory states, so they can only ever be equivalent to each other, // and not to constants, etc. DenseMap MemoryAccessToClass; // We could, if we wanted, build MemoryPhiExpressions and // MemoryVariableExpressions, etc, and value number them the same way we value // number phi expressions. For the moment, this seems like overkill. They // can only exist in one of three states: they can be TOP (equal to // everything), Equivalent to something else, or unique. Because we do not // create expressions for them, we need to simulate leader change not just // when they change class, but when they change state. Note: We can do the // same thing for phis, and avoid having phi expressions if we wanted, We // should eventually unify in one direction or the other, so this is a little // bit of an experiment in which turns out easier to maintain. enum MemoryPhiState { MPS_Invalid, MPS_TOP, MPS_Equivalent, MPS_Unique }; DenseMap MemoryPhiState; enum InstCycleState { ICS_Unknown, ICS_CycleFree, ICS_Cycle }; mutable DenseMap InstCycleState; // Expression to class mapping. using ExpressionClassMap = DenseMap; ExpressionClassMap ExpressionToClass; // We have a single expression that represents currently DeadExpressions. // For dead expressions we can prove will stay dead, we mark them with // DFS number zero. However, it's possible in the case of phi nodes // for us to assume/prove all arguments are dead during fixpointing. // We use DeadExpression for that case. DeadExpression *SingletonDeadExpression = nullptr; // Which values have changed as a result of leader changes. SmallPtrSet LeaderChanges; // Reachability info. using BlockEdge = BasicBlockEdge; DenseSet ReachableEdges; SmallPtrSet ReachableBlocks; // This is a bitvector because, on larger functions, we may have // thousands of touched instructions at once (entire blocks, // instructions with hundreds of uses, etc). Even with optimization // for when we mark whole blocks as touched, when this was a // SmallPtrSet or DenseSet, for some functions, we spent >20% of all // the time in GVN just managing this list. The bitvector, on the // other hand, efficiently supports test/set/clear of both // individual and ranges, as well as "find next element" This // enables us to use it as a worklist with essentially 0 cost. BitVector TouchedInstructions; DenseMap> BlockInstRange; #ifndef NDEBUG // Debugging for how many times each block and instruction got processed. DenseMap ProcessedCount; #endif // DFS info. // This contains a mapping from Instructions to DFS numbers. // The numbering starts at 1. An instruction with DFS number zero // means that the instruction is dead. DenseMap InstrDFS; // This contains the mapping DFS numbers to instructions. SmallVector DFSToInstr; // Deletion info. SmallPtrSet InstructionsToErase; public: NewGVN(Function &F, DominatorTree *DT, AssumptionCache *AC, TargetLibraryInfo *TLI, AliasAnalysis *AA, MemorySSA *MSSA, const DataLayout &DL) : F(F), DT(DT), TLI(TLI), AA(AA), MSSA(MSSA), DL(DL), PredInfo(make_unique(F, *DT, *AC)), SQ(DL, TLI, DT, AC) { } bool runGVN(); private: // Expression handling. const Expression *createExpression(Instruction *) const; - const Expression *createBinaryExpression(unsigned, Type *, Value *, - Value *) const; + const Expression *createBinaryExpression(unsigned, Type *, Value *, Value *, + Instruction *) const; PHIExpression *createPHIExpression(Instruction *, bool &HasBackEdge, bool &OriginalOpsConstant) const; const DeadExpression *createDeadExpression() const; const VariableExpression *createVariableExpression(Value *) const; const ConstantExpression *createConstantExpression(Constant *) const; const Expression *createVariableOrConstant(Value *V) const; const UnknownExpression *createUnknownExpression(Instruction *) const; const StoreExpression *createStoreExpression(StoreInst *, const MemoryAccess *) const; LoadExpression *createLoadExpression(Type *, Value *, LoadInst *, const MemoryAccess *) const; const CallExpression *createCallExpression(CallInst *, const MemoryAccess *) const; const AggregateValueExpression * createAggregateValueExpression(Instruction *) const; bool setBasicExpressionInfo(Instruction *, BasicExpression *) const; // Congruence class handling. CongruenceClass *createCongruenceClass(Value *Leader, const Expression *E) { auto *result = new CongruenceClass(NextCongruenceNum++, Leader, E); CongruenceClasses.emplace_back(result); return result; } CongruenceClass *createMemoryClass(MemoryAccess *MA) { auto *CC = createCongruenceClass(nullptr, nullptr); CC->setMemoryLeader(MA); return CC; } CongruenceClass *ensureLeaderOfMemoryClass(MemoryAccess *MA) { auto *CC = getMemoryClass(MA); if (CC->getMemoryLeader() != MA) CC = createMemoryClass(MA); return CC; } CongruenceClass *createSingletonCongruenceClass(Value *Member) { CongruenceClass *CClass = createCongruenceClass(Member, nullptr); CClass->insert(Member); ValueToClass[Member] = CClass; return CClass; } void initializeCongruenceClasses(Function &F); const Expression *makePossiblePhiOfOps(Instruction *, SmallPtrSetImpl &); void addPhiOfOps(PHINode *Op, BasicBlock *BB, Instruction *ExistingValue); // Value number an Instruction or MemoryPhi. void valueNumberMemoryPhi(MemoryPhi *); void valueNumberInstruction(Instruction *); // Symbolic evaluation. const Expression *checkSimplificationResults(Expression *, Instruction *, Value *) const; const Expression *performSymbolicEvaluation(Value *, SmallPtrSetImpl &) const; const Expression *performSymbolicLoadCoercion(Type *, Value *, LoadInst *, Instruction *, MemoryAccess *) const; const Expression *performSymbolicLoadEvaluation(Instruction *) const; const Expression *performSymbolicStoreEvaluation(Instruction *) const; const Expression *performSymbolicCallEvaluation(Instruction *) const; const Expression *performSymbolicPHIEvaluation(Instruction *) const; const Expression *performSymbolicAggrValueEvaluation(Instruction *) const; const Expression *performSymbolicCmpEvaluation(Instruction *) const; const Expression *performSymbolicPredicateInfoEvaluation(Instruction *) const; // Congruence finding. bool someEquivalentDominates(const Instruction *, const Instruction *) const; Value *lookupOperandLeader(Value *) const; void performCongruenceFinding(Instruction *, const Expression *); void moveValueToNewCongruenceClass(Instruction *, const Expression *, CongruenceClass *, CongruenceClass *); void moveMemoryToNewCongruenceClass(Instruction *, MemoryAccess *, CongruenceClass *, CongruenceClass *); Value *getNextValueLeader(CongruenceClass *) const; const MemoryAccess *getNextMemoryLeader(CongruenceClass *) const; bool setMemoryClass(const MemoryAccess *From, CongruenceClass *To); CongruenceClass *getMemoryClass(const MemoryAccess *MA) const; const MemoryAccess *lookupMemoryLeader(const MemoryAccess *) const; bool isMemoryAccessTOP(const MemoryAccess *) const; // Ranking unsigned int getRank(const Value *) const; bool shouldSwapOperands(const Value *, const Value *) const; // Reachability handling. void updateReachableEdge(BasicBlock *, BasicBlock *); void processOutgoingEdges(TerminatorInst *, BasicBlock *); Value *findConditionEquivalence(Value *) const; // Elimination. struct ValueDFS; void convertClassToDFSOrdered(const CongruenceClass &, SmallVectorImpl &, DenseMap &, SmallPtrSetImpl &) const; void convertClassToLoadsAndStores(const CongruenceClass &, SmallVectorImpl &) const; bool eliminateInstructions(Function &); void replaceInstruction(Instruction *, Value *); void markInstructionForDeletion(Instruction *); void deleteInstructionsInBlock(BasicBlock *); Value *findPhiOfOpsLeader(const Expression *E, const BasicBlock *BB) const; // New instruction creation. void handleNewInstruction(Instruction *){}; // Various instruction touch utilities template void for_each_found(Map &, const KeyType &, Func); template void touchAndErase(Map &, const KeyType &); void markUsersTouched(Value *); void markMemoryUsersTouched(const MemoryAccess *); void markMemoryDefTouched(const MemoryAccess *); void markPredicateUsersTouched(Instruction *); void markValueLeaderChangeTouched(CongruenceClass *CC); void markMemoryLeaderChangeTouched(CongruenceClass *CC); void markPhiOfOpsChanged(const Expression *E); void addPredicateUsers(const PredicateBase *, Instruction *) const; void addMemoryUsers(const MemoryAccess *To, MemoryAccess *U) const; void addAdditionalUsers(Value *To, Value *User) const; // Main loop of value numbering void iterateTouchedInstructions(); // Utilities. void cleanupTables(); std::pair assignDFSNumbers(BasicBlock *, unsigned); void updateProcessedCount(const Value *V); void verifyMemoryCongruency() const; void verifyIterationSettled(Function &F); void verifyStoreExpressions() const; bool singleReachablePHIPath(SmallPtrSet &, const MemoryAccess *, const MemoryAccess *) const; BasicBlock *getBlockForValue(Value *V) const; void deleteExpression(const Expression *E) const; MemoryUseOrDef *getMemoryAccess(const Instruction *) const; MemoryAccess *getDefiningAccess(const MemoryAccess *) const; MemoryPhi *getMemoryAccess(const BasicBlock *) const; template T *getMinDFSOfRange(const Range &) const; unsigned InstrToDFSNum(const Value *V) const { assert(isa(V) && "This should not be used for MemoryAccesses"); return InstrDFS.lookup(V); } unsigned InstrToDFSNum(const MemoryAccess *MA) const { return MemoryToDFSNum(MA); } Value *InstrFromDFSNum(unsigned DFSNum) { return DFSToInstr[DFSNum]; } // Given a MemoryAccess, return the relevant instruction DFS number. Note: // This deliberately takes a value so it can be used with Use's, which will // auto-convert to Value's but not to MemoryAccess's. unsigned MemoryToDFSNum(const Value *MA) const { assert(isa(MA) && "This should not be used with instructions"); return isa(MA) ? InstrToDFSNum(cast(MA)->getMemoryInst()) : InstrDFS.lookup(MA); } bool isCycleFree(const Instruction *) const; bool isBackedge(BasicBlock *From, BasicBlock *To) const; // Debug counter info. When verifying, we have to reset the value numbering // debug counter to the same state it started in to get the same results. std::pair StartingVNCounter; }; } // end anonymous namespace template static bool equalsLoadStoreHelper(const T &LHS, const Expression &RHS) { if (!isa(RHS) && !isa(RHS)) return false; return LHS.MemoryExpression::equals(RHS); } bool LoadExpression::equals(const Expression &Other) const { return equalsLoadStoreHelper(*this, Other); } bool StoreExpression::equals(const Expression &Other) const { if (!equalsLoadStoreHelper(*this, Other)) return false; // Make sure that store vs store includes the value operand. if (const auto *S = dyn_cast(&Other)) if (getStoredValue() != S->getStoredValue()) return false; return true; } // Determine if the edge From->To is a backedge bool NewGVN::isBackedge(BasicBlock *From, BasicBlock *To) const { if (From == To) return true; auto *FromDTN = DT->getNode(From); auto *ToDTN = DT->getNode(To); return RPOOrdering.lookup(FromDTN) >= RPOOrdering.lookup(ToDTN); } #ifndef NDEBUG static std::string getBlockName(const BasicBlock *B) { return DOTGraphTraits::getSimpleNodeLabel(B, nullptr); } #endif // Get a MemoryAccess for an instruction, fake or real. MemoryUseOrDef *NewGVN::getMemoryAccess(const Instruction *I) const { auto *Result = MSSA->getMemoryAccess(I); return Result ? Result : TempToMemory.lookup(I); } // Get a MemoryPhi for a basic block. These are all real. MemoryPhi *NewGVN::getMemoryAccess(const BasicBlock *BB) const { return MSSA->getMemoryAccess(BB); } // Get the basic block from an instruction/memory value. BasicBlock *NewGVN::getBlockForValue(Value *V) const { if (auto *I = dyn_cast(V)) { auto *Parent = I->getParent(); if (Parent) return Parent; Parent = TempToBlock.lookup(V); assert(Parent && "Every fake instruction should have a block"); return Parent; } auto *MP = dyn_cast(V); assert(MP && "Should have been an instruction or a MemoryPhi"); return MP->getBlock(); } // Delete a definitely dead expression, so it can be reused by the expression // allocator. Some of these are not in creation functions, so we have to accept // const versions. void NewGVN::deleteExpression(const Expression *E) const { assert(isa(E)); auto *BE = cast(E); const_cast(BE)->deallocateOperands(ArgRecycler); ExpressionAllocator.Deallocate(E); } PHIExpression *NewGVN::createPHIExpression(Instruction *I, bool &HasBackedge, bool &OriginalOpsConstant) const { BasicBlock *PHIBlock = getBlockForValue(I); auto *PN = cast(I); auto *E = new (ExpressionAllocator) PHIExpression(PN->getNumOperands(), PHIBlock); E->allocateOperands(ArgRecycler, ExpressionAllocator); E->setType(I->getType()); E->setOpcode(I->getOpcode()); // NewGVN assumes the operands of a PHI node are in a consistent order across // PHIs. LLVM doesn't seem to always guarantee this. While we need to fix // this in LLVM at some point we don't want GVN to find wrong congruences. // Therefore, here we sort uses in predecessor order. // We're sorting the values by pointer. In theory this might be cause of // non-determinism, but here we don't rely on the ordering for anything // significant, e.g. we don't create new instructions based on it so we're // fine. SmallVector PHIOperands; for (const Use &U : PN->operands()) PHIOperands.push_back(&U); std::sort(PHIOperands.begin(), PHIOperands.end(), [&](const Use *U1, const Use *U2) { return PN->getIncomingBlock(*U1) < PN->getIncomingBlock(*U2); }); // Filter out unreachable phi operands. auto Filtered = make_filter_range(PHIOperands, [&](const Use *U) { if (*U == PN) return false; if (!ReachableEdges.count({PN->getIncomingBlock(*U), PHIBlock})) return false; // Things in TOPClass are equivalent to everything. if (ValueToClass.lookup(*U) == TOPClass) return false; return lookupOperandLeader(*U) != PN; }); std::transform(Filtered.begin(), Filtered.end(), op_inserter(E), [&](const Use *U) -> Value * { auto *BB = PN->getIncomingBlock(*U); HasBackedge = HasBackedge || isBackedge(BB, PHIBlock); OriginalOpsConstant = OriginalOpsConstant && isa(*U); return lookupOperandLeader(*U); }); return E; } // Set basic expression info (Arguments, type, opcode) for Expression // E from Instruction I in block B. bool NewGVN::setBasicExpressionInfo(Instruction *I, BasicExpression *E) const { bool AllConstant = true; if (auto *GEP = dyn_cast(I)) E->setType(GEP->getSourceElementType()); else E->setType(I->getType()); E->setOpcode(I->getOpcode()); E->allocateOperands(ArgRecycler, ExpressionAllocator); // Transform the operand array into an operand leader array, and keep track of // whether all members are constant. std::transform(I->op_begin(), I->op_end(), op_inserter(E), [&](Value *O) { auto Operand = lookupOperandLeader(O); AllConstant = AllConstant && isa(Operand); return Operand; }); return AllConstant; } const Expression *NewGVN::createBinaryExpression(unsigned Opcode, Type *T, - Value *Arg1, - Value *Arg2) const { + Value *Arg1, Value *Arg2, + Instruction *I) const { auto *E = new (ExpressionAllocator) BasicExpression(2); E->setType(T); E->setOpcode(Opcode); E->allocateOperands(ArgRecycler, ExpressionAllocator); if (Instruction::isCommutative(Opcode)) { // Ensure that commutative instructions that only differ by a permutation // of their operands get the same value number by sorting the operand value // numbers. Since all commutative instructions have two operands it is more // efficient to sort by hand rather than using, say, std::sort. if (shouldSwapOperands(Arg1, Arg2)) std::swap(Arg1, Arg2); } E->op_push_back(lookupOperandLeader(Arg1)); E->op_push_back(lookupOperandLeader(Arg2)); Value *V = SimplifyBinOp(Opcode, E->getOperand(0), E->getOperand(1), SQ); - if (const Expression *SimplifiedE = checkSimplificationResults(E, nullptr, V)) + if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V)) return SimplifiedE; return E; } // Take a Value returned by simplification of Expression E/Instruction // I, and see if it resulted in a simpler expression. If so, return // that expression. // TODO: Once finished, this should not take an Instruction, we only // use it for printing. const Expression *NewGVN::checkSimplificationResults(Expression *E, Instruction *I, Value *V) const { if (!V) return nullptr; if (auto *C = dyn_cast(V)) { if (I) DEBUG(dbgs() << "Simplified " << *I << " to " << " constant " << *C << "\n"); NumGVNOpsSimplified++; assert(isa(E) && "We should always have had a basic expression here"); deleteExpression(E); return createConstantExpression(C); } else if (isa(V) || isa(V)) { if (I) DEBUG(dbgs() << "Simplified " << *I << " to " << " variable " << *V << "\n"); deleteExpression(E); return createVariableExpression(V); } CongruenceClass *CC = ValueToClass.lookup(V); if (CC && CC->getDefiningExpr()) { // If we simplified to something else, we need to communicate // that we're users of the value we simplified to. if (I != V) { // Don't add temporary instructions to the user lists. if (!AllTempInstructions.count(I)) addAdditionalUsers(V, I); } if (I) DEBUG(dbgs() << "Simplified " << *I << " to " << " expression " << *CC->getDefiningExpr() << "\n"); NumGVNOpsSimplified++; deleteExpression(E); return CC->getDefiningExpr(); } return nullptr; } const Expression *NewGVN::createExpression(Instruction *I) const { auto *E = new (ExpressionAllocator) BasicExpression(I->getNumOperands()); bool AllConstant = setBasicExpressionInfo(I, E); if (I->isCommutative()) { // Ensure that commutative instructions that only differ by a permutation // of their operands get the same value number by sorting the operand value // numbers. Since all commutative instructions have two operands it is more // efficient to sort by hand rather than using, say, std::sort. assert(I->getNumOperands() == 2 && "Unsupported commutative instruction!"); if (shouldSwapOperands(E->getOperand(0), E->getOperand(1))) E->swapOperands(0, 1); } // Perform simplificaiton // TODO: Right now we only check to see if we get a constant result. // We may get a less than constant, but still better, result for // some operations. // IE // add 0, x -> x // and x, x -> x // We should handle this by simply rewriting the expression. if (auto *CI = dyn_cast(I)) { // Sort the operand value numbers so xx get the same value // number. CmpInst::Predicate Predicate = CI->getPredicate(); if (shouldSwapOperands(E->getOperand(0), E->getOperand(1))) { E->swapOperands(0, 1); Predicate = CmpInst::getSwappedPredicate(Predicate); } E->setOpcode((CI->getOpcode() << 8) | Predicate); // TODO: 25% of our time is spent in SimplifyCmpInst with pointer operands assert(I->getOperand(0)->getType() == I->getOperand(1)->getType() && "Wrong types on cmp instruction"); assert((E->getOperand(0)->getType() == I->getOperand(0)->getType() && E->getOperand(1)->getType() == I->getOperand(1)->getType())); Value *V = SimplifyCmpInst(Predicate, E->getOperand(0), E->getOperand(1), SQ); if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V)) return SimplifiedE; } else if (isa(I)) { if (isa(E->getOperand(0)) || E->getOperand(0) == E->getOperand(1)) { assert(E->getOperand(1)->getType() == I->getOperand(1)->getType() && E->getOperand(2)->getType() == I->getOperand(2)->getType()); Value *V = SimplifySelectInst(E->getOperand(0), E->getOperand(1), E->getOperand(2), SQ); if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V)) return SimplifiedE; } } else if (I->isBinaryOp()) { Value *V = SimplifyBinOp(E->getOpcode(), E->getOperand(0), E->getOperand(1), SQ); if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V)) return SimplifiedE; } else if (auto *BI = dyn_cast(I)) { Value *V = SimplifyCastInst(BI->getOpcode(), BI->getOperand(0), BI->getType(), SQ); if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V)) return SimplifiedE; } else if (isa(I)) { Value *V = SimplifyGEPInst( E->getType(), ArrayRef(E->op_begin(), E->op_end()), SQ); if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V)) return SimplifiedE; } else if (AllConstant) { // We don't bother trying to simplify unless all of the operands // were constant. // TODO: There are a lot of Simplify*'s we could call here, if we // wanted to. The original motivating case for this code was a // zext i1 false to i8, which we don't have an interface to // simplify (IE there is no SimplifyZExt). SmallVector C; for (Value *Arg : E->operands()) C.emplace_back(cast(Arg)); if (Value *V = ConstantFoldInstOperands(I, C, DL, TLI)) if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V)) return SimplifiedE; } return E; } const AggregateValueExpression * NewGVN::createAggregateValueExpression(Instruction *I) const { if (auto *II = dyn_cast(I)) { auto *E = new (ExpressionAllocator) AggregateValueExpression(I->getNumOperands(), II->getNumIndices()); setBasicExpressionInfo(I, E); E->allocateIntOperands(ExpressionAllocator); std::copy(II->idx_begin(), II->idx_end(), int_op_inserter(E)); return E; } else if (auto *EI = dyn_cast(I)) { auto *E = new (ExpressionAllocator) AggregateValueExpression(I->getNumOperands(), EI->getNumIndices()); setBasicExpressionInfo(EI, E); E->allocateIntOperands(ExpressionAllocator); std::copy(EI->idx_begin(), EI->idx_end(), int_op_inserter(E)); return E; } llvm_unreachable("Unhandled type of aggregate value operation"); } const DeadExpression *NewGVN::createDeadExpression() const { // DeadExpression has no arguments and all DeadExpression's are the same, // so we only need one of them. return SingletonDeadExpression; } const VariableExpression *NewGVN::createVariableExpression(Value *V) const { auto *E = new (ExpressionAllocator) VariableExpression(V); E->setOpcode(V->getValueID()); return E; } const Expression *NewGVN::createVariableOrConstant(Value *V) const { if (auto *C = dyn_cast(V)) return createConstantExpression(C); return createVariableExpression(V); } const ConstantExpression *NewGVN::createConstantExpression(Constant *C) const { auto *E = new (ExpressionAllocator) ConstantExpression(C); E->setOpcode(C->getValueID()); return E; } const UnknownExpression *NewGVN::createUnknownExpression(Instruction *I) const { auto *E = new (ExpressionAllocator) UnknownExpression(I); E->setOpcode(I->getOpcode()); return E; } const CallExpression * NewGVN::createCallExpression(CallInst *CI, const MemoryAccess *MA) const { // FIXME: Add operand bundles for calls. auto *E = new (ExpressionAllocator) CallExpression(CI->getNumOperands(), CI, MA); setBasicExpressionInfo(CI, E); return E; } // Return true if some equivalent of instruction Inst dominates instruction U. bool NewGVN::someEquivalentDominates(const Instruction *Inst, const Instruction *U) const { auto *CC = ValueToClass.lookup(Inst); // This must be an instruction because we are only called from phi nodes // in the case that the value it needs to check against is an instruction. // The most likely candiates for dominance are the leader and the next leader. // The leader or nextleader will dominate in all cases where there is an // equivalent that is higher up in the dom tree. // We can't *only* check them, however, because the // dominator tree could have an infinite number of non-dominating siblings // with instructions that are in the right congruence class. // A // B C D E F G // | // H // Instruction U could be in H, with equivalents in every other sibling. // Depending on the rpo order picked, the leader could be the equivalent in // any of these siblings. if (!CC) return false; if (DT->dominates(cast(CC->getLeader()), U)) return true; if (CC->getNextLeader().first && DT->dominates(cast(CC->getNextLeader().first), U)) return true; return llvm::any_of(*CC, [&](const Value *Member) { return Member != CC->getLeader() && DT->dominates(cast(Member), U); }); } // See if we have a congruence class and leader for this operand, and if so, // return it. Otherwise, return the operand itself. Value *NewGVN::lookupOperandLeader(Value *V) const { CongruenceClass *CC = ValueToClass.lookup(V); if (CC) { // Everything in TOP is represented by undef, as it can be any value. // We do have to make sure we get the type right though, so we can't set the // RepLeader to undef. if (CC == TOPClass) return UndefValue::get(V->getType()); return CC->getStoredValue() ? CC->getStoredValue() : CC->getLeader(); } return V; } const MemoryAccess *NewGVN::lookupMemoryLeader(const MemoryAccess *MA) const { auto *CC = getMemoryClass(MA); assert(CC->getMemoryLeader() && "Every MemoryAccess should be mapped to a congruence class with a " "representative memory access"); return CC->getMemoryLeader(); } // Return true if the MemoryAccess is really equivalent to everything. This is // equivalent to the lattice value "TOP" in most lattices. This is the initial // state of all MemoryAccesses. bool NewGVN::isMemoryAccessTOP(const MemoryAccess *MA) const { return getMemoryClass(MA) == TOPClass; } LoadExpression *NewGVN::createLoadExpression(Type *LoadType, Value *PointerOp, LoadInst *LI, const MemoryAccess *MA) const { auto *E = new (ExpressionAllocator) LoadExpression(1, LI, lookupMemoryLeader(MA)); E->allocateOperands(ArgRecycler, ExpressionAllocator); E->setType(LoadType); // Give store and loads same opcode so they value number together. E->setOpcode(0); E->op_push_back(PointerOp); if (LI) E->setAlignment(LI->getAlignment()); // TODO: Value number heap versions. We may be able to discover // things alias analysis can't on it's own (IE that a store and a // load have the same value, and thus, it isn't clobbering the load). return E; } const StoreExpression * NewGVN::createStoreExpression(StoreInst *SI, const MemoryAccess *MA) const { auto *StoredValueLeader = lookupOperandLeader(SI->getValueOperand()); auto *E = new (ExpressionAllocator) StoreExpression(SI->getNumOperands(), SI, StoredValueLeader, MA); E->allocateOperands(ArgRecycler, ExpressionAllocator); E->setType(SI->getValueOperand()->getType()); // Give store and loads same opcode so they value number together. E->setOpcode(0); E->op_push_back(lookupOperandLeader(SI->getPointerOperand())); // TODO: Value number heap versions. We may be able to discover // things alias analysis can't on it's own (IE that a store and a // load have the same value, and thus, it isn't clobbering the load). return E; } const Expression *NewGVN::performSymbolicStoreEvaluation(Instruction *I) const { // Unlike loads, we never try to eliminate stores, so we do not check if they // are simple and avoid value numbering them. auto *SI = cast(I); auto *StoreAccess = getMemoryAccess(SI); // Get the expression, if any, for the RHS of the MemoryDef. const MemoryAccess *StoreRHS = StoreAccess->getDefiningAccess(); if (EnableStoreRefinement) StoreRHS = MSSAWalker->getClobberingMemoryAccess(StoreAccess); // If we bypassed the use-def chains, make sure we add a use. if (StoreRHS != StoreAccess->getDefiningAccess()) addMemoryUsers(StoreRHS, StoreAccess); StoreRHS = lookupMemoryLeader(StoreRHS); // If we are defined by ourselves, use the live on entry def. if (StoreRHS == StoreAccess) StoreRHS = MSSA->getLiveOnEntryDef(); if (SI->isSimple()) { // See if we are defined by a previous store expression, it already has a // value, and it's the same value as our current store. FIXME: Right now, we // only do this for simple stores, we should expand to cover memcpys, etc. const auto *LastStore = createStoreExpression(SI, StoreRHS); const auto *LastCC = ExpressionToClass.lookup(LastStore); // We really want to check whether the expression we matched was a store. No // easy way to do that. However, we can check that the class we found has a // store, which, assuming the value numbering state is not corrupt, is // sufficient, because we must also be equivalent to that store's expression // for it to be in the same class as the load. if (LastCC && LastCC->getStoredValue() == LastStore->getStoredValue()) return LastStore; // Also check if our value operand is defined by a load of the same memory // location, and the memory state is the same as it was then (otherwise, it // could have been overwritten later. See test32 in // transforms/DeadStoreElimination/simple.ll). if (auto *LI = dyn_cast(LastStore->getStoredValue())) if ((lookupOperandLeader(LI->getPointerOperand()) == LastStore->getOperand(0)) && (lookupMemoryLeader(getMemoryAccess(LI)->getDefiningAccess()) == StoreRHS)) return LastStore; deleteExpression(LastStore); } // If the store is not equivalent to anything, value number it as a store that // produces a unique memory state (instead of using it's MemoryUse, we use // it's MemoryDef). return createStoreExpression(SI, StoreAccess); } // See if we can extract the value of a loaded pointer from a load, a store, or // a memory instruction. const Expression * NewGVN::performSymbolicLoadCoercion(Type *LoadType, Value *LoadPtr, LoadInst *LI, Instruction *DepInst, MemoryAccess *DefiningAccess) const { assert((!LI || LI->isSimple()) && "Not a simple load"); if (auto *DepSI = dyn_cast(DepInst)) { // Can't forward from non-atomic to atomic without violating memory model. // Also don't need to coerce if they are the same type, we will just // propogate.. if (LI->isAtomic() > DepSI->isAtomic() || LoadType == DepSI->getValueOperand()->getType()) return nullptr; int Offset = analyzeLoadFromClobberingStore(LoadType, LoadPtr, DepSI, DL); if (Offset >= 0) { if (auto *C = dyn_cast( lookupOperandLeader(DepSI->getValueOperand()))) { DEBUG(dbgs() << "Coercing load from store " << *DepSI << " to constant " << *C << "\n"); return createConstantExpression( getConstantStoreValueForLoad(C, Offset, LoadType, DL)); } } } else if (LoadInst *DepLI = dyn_cast(DepInst)) { // Can't forward from non-atomic to atomic without violating memory model. if (LI->isAtomic() > DepLI->isAtomic()) return nullptr; int Offset = analyzeLoadFromClobberingLoad(LoadType, LoadPtr, DepLI, DL); if (Offset >= 0) { // We can coerce a constant load into a load if (auto *C = dyn_cast(lookupOperandLeader(DepLI))) if (auto *PossibleConstant = getConstantLoadValueForLoad(C, Offset, LoadType, DL)) { DEBUG(dbgs() << "Coercing load from load " << *LI << " to constant " << *PossibleConstant << "\n"); return createConstantExpression(PossibleConstant); } } } else if (MemIntrinsic *DepMI = dyn_cast(DepInst)) { int Offset = analyzeLoadFromClobberingMemInst(LoadType, LoadPtr, DepMI, DL); if (Offset >= 0) { if (auto *PossibleConstant = getConstantMemInstValueForLoad(DepMI, Offset, LoadType, DL)) { DEBUG(dbgs() << "Coercing load from meminst " << *DepMI << " to constant " << *PossibleConstant << "\n"); return createConstantExpression(PossibleConstant); } } } // All of the below are only true if the loaded pointer is produced // by the dependent instruction. if (LoadPtr != lookupOperandLeader(DepInst) && !AA->isMustAlias(LoadPtr, DepInst)) return nullptr; // If this load really doesn't depend on anything, then we must be loading an // undef value. This can happen when loading for a fresh allocation with no // intervening stores, for example. Note that this is only true in the case // that the result of the allocation is pointer equal to the load ptr. if (isa(DepInst) || isMallocLikeFn(DepInst, TLI)) { return createConstantExpression(UndefValue::get(LoadType)); } // If this load occurs either right after a lifetime begin, // then the loaded value is undefined. else if (auto *II = dyn_cast(DepInst)) { if (II->getIntrinsicID() == Intrinsic::lifetime_start) return createConstantExpression(UndefValue::get(LoadType)); } // If this load follows a calloc (which zero initializes memory), // then the loaded value is zero else if (isCallocLikeFn(DepInst, TLI)) { return createConstantExpression(Constant::getNullValue(LoadType)); } return nullptr; } const Expression *NewGVN::performSymbolicLoadEvaluation(Instruction *I) const { auto *LI = cast(I); // We can eliminate in favor of non-simple loads, but we won't be able to // eliminate the loads themselves. if (!LI->isSimple()) return nullptr; Value *LoadAddressLeader = lookupOperandLeader(LI->getPointerOperand()); // Load of undef is undef. if (isa(LoadAddressLeader)) return createConstantExpression(UndefValue::get(LI->getType())); MemoryAccess *OriginalAccess = getMemoryAccess(I); MemoryAccess *DefiningAccess = MSSAWalker->getClobberingMemoryAccess(OriginalAccess); if (!MSSA->isLiveOnEntryDef(DefiningAccess)) { if (auto *MD = dyn_cast(DefiningAccess)) { Instruction *DefiningInst = MD->getMemoryInst(); // If the defining instruction is not reachable, replace with undef. if (!ReachableBlocks.count(DefiningInst->getParent())) return createConstantExpression(UndefValue::get(LI->getType())); // This will handle stores and memory insts. We only do if it the // defining access has a different type, or it is a pointer produced by // certain memory operations that cause the memory to have a fixed value // (IE things like calloc). if (const auto *CoercionResult = performSymbolicLoadCoercion(LI->getType(), LoadAddressLeader, LI, DefiningInst, DefiningAccess)) return CoercionResult; } } const Expression *E = createLoadExpression(LI->getType(), LoadAddressLeader, LI, DefiningAccess); return E; } const Expression * NewGVN::performSymbolicPredicateInfoEvaluation(Instruction *I) const { auto *PI = PredInfo->getPredicateInfoFor(I); if (!PI) return nullptr; DEBUG(dbgs() << "Found predicate info from instruction !\n"); auto *PWC = dyn_cast(PI); if (!PWC) return nullptr; auto *CopyOf = I->getOperand(0); auto *Cond = PWC->Condition; // If this a copy of the condition, it must be either true or false depending // on the predicate info type and edge if (CopyOf == Cond) { // We should not need to add predicate users because the predicate info is // already a use of this operand. if (isa(PI)) return createConstantExpression(ConstantInt::getTrue(Cond->getType())); if (auto *PBranch = dyn_cast(PI)) { if (PBranch->TrueEdge) return createConstantExpression(ConstantInt::getTrue(Cond->getType())); return createConstantExpression(ConstantInt::getFalse(Cond->getType())); } if (auto *PSwitch = dyn_cast(PI)) return createConstantExpression(cast(PSwitch->CaseValue)); } // Not a copy of the condition, so see what the predicates tell us about this // value. First, though, we check to make sure the value is actually a copy // of one of the condition operands. It's possible, in certain cases, for it // to be a copy of a predicateinfo copy. In particular, if two branch // operations use the same condition, and one branch dominates the other, we // will end up with a copy of a copy. This is currently a small deficiency in // predicateinfo. What will end up happening here is that we will value // number both copies the same anyway. // Everything below relies on the condition being a comparison. auto *Cmp = dyn_cast(Cond); if (!Cmp) return nullptr; if (CopyOf != Cmp->getOperand(0) && CopyOf != Cmp->getOperand(1)) { DEBUG(dbgs() << "Copy is not of any condition operands!\n"); return nullptr; } Value *FirstOp = lookupOperandLeader(Cmp->getOperand(0)); Value *SecondOp = lookupOperandLeader(Cmp->getOperand(1)); bool SwappedOps = false; // Sort the ops if (shouldSwapOperands(FirstOp, SecondOp)) { std::swap(FirstOp, SecondOp); SwappedOps = true; } CmpInst::Predicate Predicate = SwappedOps ? Cmp->getSwappedPredicate() : Cmp->getPredicate(); if (isa(PI)) { // If the comparison is true when the operands are equal, then we know the // operands are equal, because assumes must always be true. if (CmpInst::isTrueWhenEqual(Predicate)) { addPredicateUsers(PI, I); addAdditionalUsers(Cmp->getOperand(0), I); return createVariableOrConstant(FirstOp); } } if (const auto *PBranch = dyn_cast(PI)) { // If we are *not* a copy of the comparison, we may equal to the other // operand when the predicate implies something about equality of // operations. In particular, if the comparison is true/false when the // operands are equal, and we are on the right edge, we know this operation // is equal to something. if ((PBranch->TrueEdge && Predicate == CmpInst::ICMP_EQ) || (!PBranch->TrueEdge && Predicate == CmpInst::ICMP_NE)) { addPredicateUsers(PI, I); addAdditionalUsers(Cmp->getOperand(0), I); return createVariableOrConstant(FirstOp); } // Handle the special case of floating point. if (((PBranch->TrueEdge && Predicate == CmpInst::FCMP_OEQ) || (!PBranch->TrueEdge && Predicate == CmpInst::FCMP_UNE)) && isa(FirstOp) && !cast(FirstOp)->isZero()) { addPredicateUsers(PI, I); addAdditionalUsers(Cmp->getOperand(0), I); return createConstantExpression(cast(FirstOp)); } } return nullptr; } // Evaluate read only and pure calls, and create an expression result. const Expression *NewGVN::performSymbolicCallEvaluation(Instruction *I) const { auto *CI = cast(I); if (auto *II = dyn_cast(I)) { // Instrinsics with the returned attribute are copies of arguments. if (auto *ReturnedValue = II->getReturnedArgOperand()) { if (II->getIntrinsicID() == Intrinsic::ssa_copy) if (const auto *Result = performSymbolicPredicateInfoEvaluation(I)) return Result; return createVariableOrConstant(ReturnedValue); } } if (AA->doesNotAccessMemory(CI)) { return createCallExpression(CI, TOPClass->getMemoryLeader()); } else if (AA->onlyReadsMemory(CI)) { MemoryAccess *DefiningAccess = MSSAWalker->getClobberingMemoryAccess(CI); return createCallExpression(CI, DefiningAccess); } return nullptr; } // Retrieve the memory class for a given MemoryAccess. CongruenceClass *NewGVN::getMemoryClass(const MemoryAccess *MA) const { auto *Result = MemoryAccessToClass.lookup(MA); assert(Result && "Should have found memory class"); return Result; } // Update the MemoryAccess equivalence table to say that From is equal to To, // and return true if this is different from what already existed in the table. bool NewGVN::setMemoryClass(const MemoryAccess *From, CongruenceClass *NewClass) { assert(NewClass && "Every MemoryAccess should be getting mapped to a non-null class"); DEBUG(dbgs() << "Setting " << *From); DEBUG(dbgs() << " equivalent to congruence class "); DEBUG(dbgs() << NewClass->getID() << " with current MemoryAccess leader "); DEBUG(dbgs() << *NewClass->getMemoryLeader() << "\n"); auto LookupResult = MemoryAccessToClass.find(From); bool Changed = false; // If it's already in the table, see if the value changed. if (LookupResult != MemoryAccessToClass.end()) { auto *OldClass = LookupResult->second; if (OldClass != NewClass) { // If this is a phi, we have to handle memory member updates. if (auto *MP = dyn_cast(From)) { OldClass->memory_erase(MP); NewClass->memory_insert(MP); // This may have killed the class if it had no non-memory members if (OldClass->getMemoryLeader() == From) { if (OldClass->definesNoMemory()) { OldClass->setMemoryLeader(nullptr); } else { OldClass->setMemoryLeader(getNextMemoryLeader(OldClass)); DEBUG(dbgs() << "Memory class leader change for class " << OldClass->getID() << " to " << *OldClass->getMemoryLeader() << " due to removal of a memory member " << *From << "\n"); markMemoryLeaderChangeTouched(OldClass); } } } // It wasn't equivalent before, and now it is. LookupResult->second = NewClass; Changed = true; } } return Changed; } // Determine if a instruction is cycle-free. That means the values in the // instruction don't depend on any expressions that can change value as a result // of the instruction. For example, a non-cycle free instruction would be v = // phi(0, v+1). bool NewGVN::isCycleFree(const Instruction *I) const { // In order to compute cycle-freeness, we do SCC finding on the instruction, // and see what kind of SCC it ends up in. If it is a singleton, it is // cycle-free. If it is not in a singleton, it is only cycle free if the // other members are all phi nodes (as they do not compute anything, they are // copies). auto ICS = InstCycleState.lookup(I); if (ICS == ICS_Unknown) { SCCFinder.Start(I); auto &SCC = SCCFinder.getComponentFor(I); // It's cycle free if it's size 1 or or the SCC is *only* phi nodes. if (SCC.size() == 1) InstCycleState.insert({I, ICS_CycleFree}); else { bool AllPhis = llvm::all_of(SCC, [](const Value *V) { return isa(V); }); ICS = AllPhis ? ICS_CycleFree : ICS_Cycle; for (auto *Member : SCC) if (auto *MemberPhi = dyn_cast(Member)) InstCycleState.insert({MemberPhi, ICS}); } } if (ICS == ICS_Cycle) return false; return true; } // Evaluate PHI nodes symbolically, and create an expression result. const Expression *NewGVN::performSymbolicPHIEvaluation(Instruction *I) const { // True if one of the incoming phi edges is a backedge. bool HasBackedge = false; // All constant tracks the state of whether all the *original* phi operands // This is really shorthand for "this phi cannot cycle due to forward // change in value of the phi is guaranteed not to later change the value of // the phi. IE it can't be v = phi(undef, v+1) bool AllConstant = true; auto *E = cast(createPHIExpression(I, HasBackedge, AllConstant)); // We match the semantics of SimplifyPhiNode from InstructionSimplify here. // See if all arguments are the same. // We track if any were undef because they need special handling. bool HasUndef = false; auto Filtered = make_filter_range(E->operands(), [&](Value *Arg) { if (isa(Arg)) { HasUndef = true; return false; } return true; }); // If we are left with no operands, it's dead. if (Filtered.begin() == Filtered.end()) { // If it has undef at this point, it means there are no-non-undef arguments, // and thus, the value of the phi node must be undef. if (HasUndef) { DEBUG(dbgs() << "PHI Node " << *I << " has no non-undef arguments, valuing it as undef\n"); return createConstantExpression(UndefValue::get(I->getType())); } DEBUG(dbgs() << "No arguments of PHI node " << *I << " are live\n"); deleteExpression(E); return createDeadExpression(); } unsigned NumOps = 0; Value *AllSameValue = *(Filtered.begin()); ++Filtered.begin(); // Can't use std::equal here, sadly, because filter.begin moves. if (llvm::all_of(Filtered, [&](Value *Arg) { ++NumOps; return Arg == AllSameValue; })) { // In LLVM's non-standard representation of phi nodes, it's possible to have // phi nodes with cycles (IE dependent on other phis that are .... dependent // on the original phi node), especially in weird CFG's where some arguments // are unreachable, or uninitialized along certain paths. This can cause // infinite loops during evaluation. We work around this by not trying to // really evaluate them independently, but instead using a variable // expression to say if one is equivalent to the other. // We also special case undef, so that if we have an undef, we can't use the // common value unless it dominates the phi block. if (HasUndef) { // If we have undef and at least one other value, this is really a // multivalued phi, and we need to know if it's cycle free in order to // evaluate whether we can ignore the undef. The other parts of this are // just shortcuts. If there is no backedge, or all operands are // constants, or all operands are ignored but the undef, it also must be // cycle free. if (!AllConstant && HasBackedge && NumOps > 0 && !isa(AllSameValue) && !isCycleFree(I)) return E; // Only have to check for instructions if (auto *AllSameInst = dyn_cast(AllSameValue)) if (!someEquivalentDominates(AllSameInst, I)) return E; } // Can't simplify to something that comes later in the iteration. // Otherwise, when and if it changes congruence class, we will never catch // up. We will always be a class behind it. if (isa(AllSameValue) && InstrToDFSNum(AllSameValue) > InstrToDFSNum(I)) return E; NumGVNPhisAllSame++; DEBUG(dbgs() << "Simplified PHI node " << *I << " to " << *AllSameValue << "\n"); deleteExpression(E); return createVariableOrConstant(AllSameValue); } return E; } const Expression * NewGVN::performSymbolicAggrValueEvaluation(Instruction *I) const { if (auto *EI = dyn_cast(I)) { auto *II = dyn_cast(EI->getAggregateOperand()); if (II && EI->getNumIndices() == 1 && *EI->idx_begin() == 0) { unsigned Opcode = 0; // EI might be an extract from one of our recognised intrinsics. If it // is we'll synthesize a semantically equivalent expression instead on // an extract value expression. switch (II->getIntrinsicID()) { case Intrinsic::sadd_with_overflow: case Intrinsic::uadd_with_overflow: Opcode = Instruction::Add; break; case Intrinsic::ssub_with_overflow: case Intrinsic::usub_with_overflow: Opcode = Instruction::Sub; break; case Intrinsic::smul_with_overflow: case Intrinsic::umul_with_overflow: Opcode = Instruction::Mul; break; default: break; } if (Opcode != 0) { // Intrinsic recognized. Grab its args to finish building the // expression. assert(II->getNumArgOperands() == 2 && "Expect two args for recognised intrinsics."); - return createBinaryExpression( - Opcode, EI->getType(), II->getArgOperand(0), II->getArgOperand(1)); + return createBinaryExpression(Opcode, EI->getType(), + II->getArgOperand(0), + II->getArgOperand(1), I); } } } return createAggregateValueExpression(I); } const Expression *NewGVN::performSymbolicCmpEvaluation(Instruction *I) const { auto *CI = dyn_cast(I); // See if our operands are equal to those of a previous predicate, and if so, // if it implies true or false. auto Op0 = lookupOperandLeader(CI->getOperand(0)); auto Op1 = lookupOperandLeader(CI->getOperand(1)); auto OurPredicate = CI->getPredicate(); if (shouldSwapOperands(Op0, Op1)) { std::swap(Op0, Op1); OurPredicate = CI->getSwappedPredicate(); } // Avoid processing the same info twice const PredicateBase *LastPredInfo = nullptr; // See if we know something about the comparison itself, like it is the target // of an assume. auto *CmpPI = PredInfo->getPredicateInfoFor(I); if (dyn_cast_or_null(CmpPI)) return createConstantExpression(ConstantInt::getTrue(CI->getType())); if (Op0 == Op1) { // This condition does not depend on predicates, no need to add users if (CI->isTrueWhenEqual()) return createConstantExpression(ConstantInt::getTrue(CI->getType())); else if (CI->isFalseWhenEqual()) return createConstantExpression(ConstantInt::getFalse(CI->getType())); } // NOTE: Because we are comparing both operands here and below, and using // previous comparisons, we rely on fact that predicateinfo knows to mark // comparisons that use renamed operands as users of the earlier comparisons. // It is *not* enough to just mark predicateinfo renamed operands as users of // the earlier comparisons, because the *other* operand may have changed in a // previous iteration. // Example: // icmp slt %a, %b // %b.0 = ssa.copy(%b) // false branch: // icmp slt %c, %b.0 // %c and %a may start out equal, and thus, the code below will say the second // %icmp is false. c may become equal to something else, and in that case the // %second icmp *must* be reexamined, but would not if only the renamed // %operands are considered users of the icmp. // *Currently* we only check one level of comparisons back, and only mark one // level back as touched when changes appen . If you modify this code to look // back farther through comparisons, you *must* mark the appropriate // comparisons as users in PredicateInfo.cpp, or you will cause bugs. See if // we know something just from the operands themselves // See if our operands have predicate info, so that we may be able to derive // something from a previous comparison. for (const auto &Op : CI->operands()) { auto *PI = PredInfo->getPredicateInfoFor(Op); if (const auto *PBranch = dyn_cast_or_null(PI)) { if (PI == LastPredInfo) continue; LastPredInfo = PI; // TODO: Along the false edge, we may know more things too, like icmp of // same operands is false. // TODO: We only handle actual comparison conditions below, not and/or. auto *BranchCond = dyn_cast(PBranch->Condition); if (!BranchCond) continue; auto *BranchOp0 = lookupOperandLeader(BranchCond->getOperand(0)); auto *BranchOp1 = lookupOperandLeader(BranchCond->getOperand(1)); auto BranchPredicate = BranchCond->getPredicate(); if (shouldSwapOperands(BranchOp0, BranchOp1)) { std::swap(BranchOp0, BranchOp1); BranchPredicate = BranchCond->getSwappedPredicate(); } if (BranchOp0 == Op0 && BranchOp1 == Op1) { if (PBranch->TrueEdge) { // If we know the previous predicate is true and we are in the true // edge then we may be implied true or false. if (CmpInst::isImpliedTrueByMatchingCmp(BranchPredicate, OurPredicate)) { addPredicateUsers(PI, I); return createConstantExpression( ConstantInt::getTrue(CI->getType())); } if (CmpInst::isImpliedFalseByMatchingCmp(BranchPredicate, OurPredicate)) { addPredicateUsers(PI, I); return createConstantExpression( ConstantInt::getFalse(CI->getType())); } } else { // Just handle the ne and eq cases, where if we have the same // operands, we may know something. if (BranchPredicate == OurPredicate) { addPredicateUsers(PI, I); // Same predicate, same ops,we know it was false, so this is false. return createConstantExpression( ConstantInt::getFalse(CI->getType())); } else if (BranchPredicate == CmpInst::getInversePredicate(OurPredicate)) { addPredicateUsers(PI, I); // Inverse predicate, we know the other was false, so this is true. return createConstantExpression( ConstantInt::getTrue(CI->getType())); } } } } } // Create expression will take care of simplifyCmpInst return createExpression(I); } // Return true if V is a value that will always be available (IE can // be placed anywhere) in the function. We don't do globals here // because they are often worse to put in place. // TODO: Separate cost from availability static bool alwaysAvailable(Value *V) { return isa(V) || isa(V); } // Substitute and symbolize the value before value numbering. const Expression * NewGVN::performSymbolicEvaluation(Value *V, SmallPtrSetImpl &Visited) const { const Expression *E = nullptr; if (auto *C = dyn_cast(V)) E = createConstantExpression(C); else if (isa(V) || isa(V)) { E = createVariableExpression(V); } else { // TODO: memory intrinsics. // TODO: Some day, we should do the forward propagation and reassociation // parts of the algorithm. auto *I = cast(V); switch (I->getOpcode()) { case Instruction::ExtractValue: case Instruction::InsertValue: E = performSymbolicAggrValueEvaluation(I); break; case Instruction::PHI: E = performSymbolicPHIEvaluation(I); break; case Instruction::Call: E = performSymbolicCallEvaluation(I); break; case Instruction::Store: E = performSymbolicStoreEvaluation(I); break; case Instruction::Load: E = performSymbolicLoadEvaluation(I); break; case Instruction::BitCast: { E = createExpression(I); } break; case Instruction::ICmp: case Instruction::FCmp: { E = performSymbolicCmpEvaluation(I); } break; case Instruction::Add: case Instruction::FAdd: case Instruction::Sub: case Instruction::FSub: case Instruction::Mul: case Instruction::FMul: case Instruction::UDiv: case Instruction::SDiv: case Instruction::FDiv: case Instruction::URem: case Instruction::SRem: case Instruction::FRem: case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: case Instruction::And: case Instruction::Or: case Instruction::Xor: case Instruction::Trunc: case Instruction::ZExt: case Instruction::SExt: case Instruction::FPToUI: case Instruction::FPToSI: case Instruction::UIToFP: case Instruction::SIToFP: case Instruction::FPTrunc: case Instruction::FPExt: case Instruction::PtrToInt: case Instruction::IntToPtr: case Instruction::Select: case Instruction::ExtractElement: case Instruction::InsertElement: case Instruction::ShuffleVector: case Instruction::GetElementPtr: E = createExpression(I); break; default: return nullptr; } } return E; } // Look up a container in a map, and then call a function for each thing in the // found container. template void NewGVN::for_each_found(Map &M, const KeyType &Key, Func F) { const auto Result = M.find_as(Key); if (Result != M.end()) for (typename Map::mapped_type::value_type Mapped : Result->second) F(Mapped); } // Look up a container of values/instructions in a map, and touch all the // instructions in the container. Then erase value from the map. template void NewGVN::touchAndErase(Map &M, const KeyType &Key) { const auto Result = M.find_as(Key); if (Result != M.end()) { for (const typename Map::mapped_type::value_type Mapped : Result->second) TouchedInstructions.set(InstrToDFSNum(Mapped)); M.erase(Result); } } void NewGVN::addAdditionalUsers(Value *To, Value *User) const { + assert(User && To != User); if (isa(To)) AdditionalUsers[To].insert(User); } void NewGVN::markUsersTouched(Value *V) { // Now mark the users as touched. for (auto *User : V->users()) { assert(isa(User) && "Use of value not within an instruction?"); TouchedInstructions.set(InstrToDFSNum(User)); } touchAndErase(AdditionalUsers, V); } void NewGVN::addMemoryUsers(const MemoryAccess *To, MemoryAccess *U) const { DEBUG(dbgs() << "Adding memory user " << *U << " to " << *To << "\n"); MemoryToUsers[To].insert(U); } void NewGVN::markMemoryDefTouched(const MemoryAccess *MA) { TouchedInstructions.set(MemoryToDFSNum(MA)); } void NewGVN::markMemoryUsersTouched(const MemoryAccess *MA) { if (isa(MA)) return; for (auto U : MA->users()) TouchedInstructions.set(MemoryToDFSNum(U)); touchAndErase(MemoryToUsers, MA); } // Add I to the set of users of a given predicate. void NewGVN::addPredicateUsers(const PredicateBase *PB, Instruction *I) const { // Don't add temporary instructions to the user lists. if (AllTempInstructions.count(I)) return; if (auto *PBranch = dyn_cast(PB)) PredicateToUsers[PBranch->Condition].insert(I); else if (auto *PAssume = dyn_cast(PB)) PredicateToUsers[PAssume->Condition].insert(I); } // Touch all the predicates that depend on this instruction. void NewGVN::markPredicateUsersTouched(Instruction *I) { touchAndErase(PredicateToUsers, I); } // Mark users affected by a memory leader change. void NewGVN::markMemoryLeaderChangeTouched(CongruenceClass *CC) { for (auto M : CC->memory()) markMemoryDefTouched(M); } // Touch the instructions that need to be updated after a congruence class has a // leader change, and mark changed values. void NewGVN::markValueLeaderChangeTouched(CongruenceClass *CC) { for (auto M : *CC) { if (auto *I = dyn_cast(M)) TouchedInstructions.set(InstrToDFSNum(I)); LeaderChanges.insert(M); } } // Give a range of things that have instruction DFS numbers, this will return // the member of the range with the smallest dfs number. template T *NewGVN::getMinDFSOfRange(const Range &R) const { std::pair MinDFS = {nullptr, ~0U}; for (const auto X : R) { auto DFSNum = InstrToDFSNum(X); if (DFSNum < MinDFS.second) MinDFS = {X, DFSNum}; } return MinDFS.first; } // This function returns the MemoryAccess that should be the next leader of // congruence class CC, under the assumption that the current leader is going to // disappear. const MemoryAccess *NewGVN::getNextMemoryLeader(CongruenceClass *CC) const { // TODO: If this ends up to slow, we can maintain a next memory leader like we // do for regular leaders. // Make sure there will be a leader to find assert(!CC->definesNoMemory() && "Can't get next leader if there is none"); if (CC->getStoreCount() > 0) { if (auto *NL = dyn_cast_or_null(CC->getNextLeader().first)) return getMemoryAccess(NL); // Find the store with the minimum DFS number. auto *V = getMinDFSOfRange(make_filter_range( *CC, [&](const Value *V) { return isa(V); })); return getMemoryAccess(cast(V)); } assert(CC->getStoreCount() == 0); // Given our assertion, hitting this part must mean // !OldClass->memory_empty() if (CC->memory_size() == 1) return *CC->memory_begin(); return getMinDFSOfRange(CC->memory()); } // This function returns the next value leader of a congruence class, under the // assumption that the current leader is going away. This should end up being // the next most dominating member. Value *NewGVN::getNextValueLeader(CongruenceClass *CC) const { // We don't need to sort members if there is only 1, and we don't care about // sorting the TOP class because everything either gets out of it or is // unreachable. if (CC->size() == 1 || CC == TOPClass) { return *(CC->begin()); } else if (CC->getNextLeader().first) { ++NumGVNAvoidedSortedLeaderChanges; return CC->getNextLeader().first; } else { ++NumGVNSortedLeaderChanges; // NOTE: If this ends up to slow, we can maintain a dual structure for // member testing/insertion, or keep things mostly sorted, and sort only // here, or use SparseBitVector or .... return getMinDFSOfRange(*CC); } } // Move a MemoryAccess, currently in OldClass, to NewClass, including updates to // the memory members, etc for the move. // // The invariants of this function are: // // - I must be moving to NewClass from OldClass // - The StoreCount of OldClass and NewClass is expected to have been updated // for I already if it is is a store. // - The OldClass memory leader has not been updated yet if I was the leader. void NewGVN::moveMemoryToNewCongruenceClass(Instruction *I, MemoryAccess *InstMA, CongruenceClass *OldClass, CongruenceClass *NewClass) { // If the leader is I, and we had a represenative MemoryAccess, it should // be the MemoryAccess of OldClass. assert((!InstMA || !OldClass->getMemoryLeader() || OldClass->getLeader() != I || MemoryAccessToClass.lookup(OldClass->getMemoryLeader()) == MemoryAccessToClass.lookup(InstMA)) && "Representative MemoryAccess mismatch"); // First, see what happens to the new class if (!NewClass->getMemoryLeader()) { // Should be a new class, or a store becoming a leader of a new class. assert(NewClass->size() == 1 || (isa(I) && NewClass->getStoreCount() == 1)); NewClass->setMemoryLeader(InstMA); // Mark it touched if we didn't just create a singleton DEBUG(dbgs() << "Memory class leader change for class " << NewClass->getID() << " due to new memory instruction becoming leader\n"); markMemoryLeaderChangeTouched(NewClass); } setMemoryClass(InstMA, NewClass); // Now, fixup the old class if necessary if (OldClass->getMemoryLeader() == InstMA) { if (!OldClass->definesNoMemory()) { OldClass->setMemoryLeader(getNextMemoryLeader(OldClass)); DEBUG(dbgs() << "Memory class leader change for class " << OldClass->getID() << " to " << *OldClass->getMemoryLeader() << " due to removal of old leader " << *InstMA << "\n"); markMemoryLeaderChangeTouched(OldClass); } else OldClass->setMemoryLeader(nullptr); } } // Move a value, currently in OldClass, to be part of NewClass // Update OldClass and NewClass for the move (including changing leaders, etc). void NewGVN::moveValueToNewCongruenceClass(Instruction *I, const Expression *E, CongruenceClass *OldClass, CongruenceClass *NewClass) { if (I == OldClass->getNextLeader().first) OldClass->resetNextLeader(); OldClass->erase(I); NewClass->insert(I); if (NewClass->getLeader() != I) NewClass->addPossibleNextLeader({I, InstrToDFSNum(I)}); // Handle our special casing of stores. if (auto *SI = dyn_cast(I)) { OldClass->decStoreCount(); // Okay, so when do we want to make a store a leader of a class? // If we have a store defined by an earlier load, we want the earlier load // to lead the class. // If we have a store defined by something else, we want the store to lead // the class so everything else gets the "something else" as a value. // If we have a store as the single member of the class, we want the store // as the leader if (NewClass->getStoreCount() == 0 && !NewClass->getStoredValue()) { // If it's a store expression we are using, it means we are not equivalent // to something earlier. if (auto *SE = dyn_cast(E)) { NewClass->setStoredValue(SE->getStoredValue()); markValueLeaderChangeTouched(NewClass); // Shift the new class leader to be the store DEBUG(dbgs() << "Changing leader of congruence class " << NewClass->getID() << " from " << *NewClass->getLeader() << " to " << *SI << " because store joined class\n"); // If we changed the leader, we have to mark it changed because we don't // know what it will do to symbolic evaluation. NewClass->setLeader(SI); } // We rely on the code below handling the MemoryAccess change. } NewClass->incStoreCount(); } // True if there is no memory instructions left in a class that had memory // instructions before. // If it's not a memory use, set the MemoryAccess equivalence auto *InstMA = dyn_cast_or_null(getMemoryAccess(I)); if (InstMA) moveMemoryToNewCongruenceClass(I, InstMA, OldClass, NewClass); ValueToClass[I] = NewClass; // See if we destroyed the class or need to swap leaders. if (OldClass->empty() && OldClass != TOPClass) { if (OldClass->getDefiningExpr()) { DEBUG(dbgs() << "Erasing expression " << *OldClass->getDefiningExpr() << " from table\n"); // We erase it as an exact expression to make sure we don't just erase an // equivalent one. auto Iter = ExpressionToClass.find_as( ExactEqualsExpression(*OldClass->getDefiningExpr())); if (Iter != ExpressionToClass.end()) ExpressionToClass.erase(Iter); #ifdef EXPENSIVE_CHECKS assert( (*OldClass->getDefiningExpr() != *E || ExpressionToClass.lookup(E)) && "We erased the expression we just inserted, which should not happen"); #endif } } else if (OldClass->getLeader() == I) { // When the leader changes, the value numbering of // everything may change due to symbolization changes, so we need to // reprocess. DEBUG(dbgs() << "Value class leader change for class " << OldClass->getID() << "\n"); ++NumGVNLeaderChanges; // Destroy the stored value if there are no more stores to represent it. // Note that this is basically clean up for the expression removal that // happens below. If we remove stores from a class, we may leave it as a // class of equivalent memory phis. if (OldClass->getStoreCount() == 0) { if (OldClass->getStoredValue()) OldClass->setStoredValue(nullptr); } OldClass->setLeader(getNextValueLeader(OldClass)); OldClass->resetNextLeader(); markValueLeaderChangeTouched(OldClass); } } // For a given expression, mark the phi of ops instructions that could have // changed as a result. void NewGVN::markPhiOfOpsChanged(const Expression *E) { touchAndErase(ExpressionToPhiOfOps, ExactEqualsExpression(*E)); } // Perform congruence finding on a given value numbering expression. void NewGVN::performCongruenceFinding(Instruction *I, const Expression *E) { // This is guaranteed to return something, since it will at least find // TOP. CongruenceClass *IClass = ValueToClass.lookup(I); assert(IClass && "Should have found a IClass"); // Dead classes should have been eliminated from the mapping. assert(!IClass->isDead() && "Found a dead class"); CongruenceClass *EClass = nullptr; if (const auto *VE = dyn_cast(E)) { EClass = ValueToClass.lookup(VE->getVariableValue()); } else if (isa(E)) { EClass = TOPClass; } if (!EClass) { auto lookupResult = ExpressionToClass.insert({E, nullptr}); // If it's not in the value table, create a new congruence class. if (lookupResult.second) { CongruenceClass *NewClass = createCongruenceClass(nullptr, E); auto place = lookupResult.first; place->second = NewClass; // Constants and variables should always be made the leader. if (const auto *CE = dyn_cast(E)) { NewClass->setLeader(CE->getConstantValue()); } else if (const auto *SE = dyn_cast(E)) { StoreInst *SI = SE->getStoreInst(); NewClass->setLeader(SI); NewClass->setStoredValue(SE->getStoredValue()); // The RepMemoryAccess field will be filled in properly by the // moveValueToNewCongruenceClass call. } else { NewClass->setLeader(I); } assert(!isa(E) && "VariableExpression should have been handled already"); EClass = NewClass; DEBUG(dbgs() << "Created new congruence class for " << *I << " using expression " << *E << " at " << NewClass->getID() << " and leader " << *(NewClass->getLeader())); if (NewClass->getStoredValue()) DEBUG(dbgs() << " and stored value " << *(NewClass->getStoredValue())); DEBUG(dbgs() << "\n"); } else { EClass = lookupResult.first->second; if (isa(E)) assert((isa(EClass->getLeader()) || (EClass->getStoredValue() && isa(EClass->getStoredValue()))) && "Any class with a constant expression should have a " "constant leader"); assert(EClass && "Somehow don't have an eclass"); assert(!EClass->isDead() && "We accidentally looked up a dead class"); } } bool ClassChanged = IClass != EClass; bool LeaderChanged = LeaderChanges.erase(I); if (ClassChanged || LeaderChanged) { DEBUG(dbgs() << "New class " << EClass->getID() << " for expression " << *E << "\n"); if (ClassChanged) { moveValueToNewCongruenceClass(I, E, IClass, EClass); markPhiOfOpsChanged(E); } markUsersTouched(I); if (MemoryAccess *MA = getMemoryAccess(I)) markMemoryUsersTouched(MA); if (auto *CI = dyn_cast(I)) markPredicateUsersTouched(CI); } // If we changed the class of the store, we want to ensure nothing finds the // old store expression. In particular, loads do not compare against stored // value, so they will find old store expressions (and associated class // mappings) if we leave them in the table. if (ClassChanged && isa(I)) { auto *OldE = ValueToExpression.lookup(I); // It could just be that the old class died. We don't want to erase it if we // just moved classes. if (OldE && isa(OldE) && *E != *OldE) { // Erase this as an exact expression to ensure we don't erase expressions // equivalent to it. auto Iter = ExpressionToClass.find_as(ExactEqualsExpression(*OldE)); if (Iter != ExpressionToClass.end()) ExpressionToClass.erase(Iter); } } ValueToExpression[I] = E; } // Process the fact that Edge (from, to) is reachable, including marking // any newly reachable blocks and instructions for processing. void NewGVN::updateReachableEdge(BasicBlock *From, BasicBlock *To) { // Check if the Edge was reachable before. if (ReachableEdges.insert({From, To}).second) { // If this block wasn't reachable before, all instructions are touched. if (ReachableBlocks.insert(To).second) { DEBUG(dbgs() << "Block " << getBlockName(To) << " marked reachable\n"); const auto &InstRange = BlockInstRange.lookup(To); TouchedInstructions.set(InstRange.first, InstRange.second); } else { DEBUG(dbgs() << "Block " << getBlockName(To) << " was reachable, but new edge {" << getBlockName(From) << "," << getBlockName(To) << "} to it found\n"); // We've made an edge reachable to an existing block, which may // impact predicates. Otherwise, only mark the phi nodes as touched, as // they are the only thing that depend on new edges. Anything using their // values will get propagated to if necessary. if (MemoryAccess *MemPhi = getMemoryAccess(To)) TouchedInstructions.set(InstrToDFSNum(MemPhi)); auto BI = To->begin(); while (isa(BI)) { TouchedInstructions.set(InstrToDFSNum(&*BI)); ++BI; } for_each_found(PHIOfOpsPHIs, To, [&](const PHINode *I) { TouchedInstructions.set(InstrToDFSNum(I)); }); } } } // Given a predicate condition (from a switch, cmp, or whatever) and a block, // see if we know some constant value for it already. Value *NewGVN::findConditionEquivalence(Value *Cond) const { auto Result = lookupOperandLeader(Cond); return isa(Result) ? Result : nullptr; } // Process the outgoing edges of a block for reachability. void NewGVN::processOutgoingEdges(TerminatorInst *TI, BasicBlock *B) { // Evaluate reachability of terminator instruction. BranchInst *BR; if ((BR = dyn_cast(TI)) && BR->isConditional()) { Value *Cond = BR->getCondition(); Value *CondEvaluated = findConditionEquivalence(Cond); if (!CondEvaluated) { if (auto *I = dyn_cast(Cond)) { const Expression *E = createExpression(I); if (const auto *CE = dyn_cast(E)) { CondEvaluated = CE->getConstantValue(); } } else if (isa(Cond)) { CondEvaluated = Cond; } } ConstantInt *CI; BasicBlock *TrueSucc = BR->getSuccessor(0); BasicBlock *FalseSucc = BR->getSuccessor(1); if (CondEvaluated && (CI = dyn_cast(CondEvaluated))) { if (CI->isOne()) { DEBUG(dbgs() << "Condition for Terminator " << *TI << " evaluated to true\n"); updateReachableEdge(B, TrueSucc); } else if (CI->isZero()) { DEBUG(dbgs() << "Condition for Terminator " << *TI << " evaluated to false\n"); updateReachableEdge(B, FalseSucc); } } else { updateReachableEdge(B, TrueSucc); updateReachableEdge(B, FalseSucc); } } else if (auto *SI = dyn_cast(TI)) { // For switches, propagate the case values into the case // destinations. // Remember how many outgoing edges there are to every successor. SmallDenseMap SwitchEdges; Value *SwitchCond = SI->getCondition(); Value *CondEvaluated = findConditionEquivalence(SwitchCond); // See if we were able to turn this switch statement into a constant. if (CondEvaluated && isa(CondEvaluated)) { auto *CondVal = cast(CondEvaluated); // We should be able to get case value for this. auto Case = *SI->findCaseValue(CondVal); if (Case.getCaseSuccessor() == SI->getDefaultDest()) { // We proved the value is outside of the range of the case. // We can't do anything other than mark the default dest as reachable, // and go home. updateReachableEdge(B, SI->getDefaultDest()); return; } // Now get where it goes and mark it reachable. BasicBlock *TargetBlock = Case.getCaseSuccessor(); updateReachableEdge(B, TargetBlock); } else { for (unsigned i = 0, e = SI->getNumSuccessors(); i != e; ++i) { BasicBlock *TargetBlock = SI->getSuccessor(i); ++SwitchEdges[TargetBlock]; updateReachableEdge(B, TargetBlock); } } } else { // Otherwise this is either unconditional, or a type we have no // idea about. Just mark successors as reachable. for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) { BasicBlock *TargetBlock = TI->getSuccessor(i); updateReachableEdge(B, TargetBlock); } // This also may be a memory defining terminator, in which case, set it // equivalent only to itself. // auto *MA = getMemoryAccess(TI); if (MA && !isa(MA)) { auto *CC = ensureLeaderOfMemoryClass(MA); if (setMemoryClass(MA, CC)) markMemoryUsersTouched(MA); } } } void NewGVN::addPhiOfOps(PHINode *Op, BasicBlock *BB, Instruction *ExistingValue) { InstrDFS[Op] = InstrToDFSNum(ExistingValue); AllTempInstructions.insert(Op); PHIOfOpsPHIs[BB].push_back(Op); TempToBlock[Op] = BB; RealToTemp[ExistingValue] = Op; } static bool okayForPHIOfOps(const Instruction *I) { return isa(I) || isa(I) || isa(I) || isa(I); } // When we see an instruction that is an op of phis, generate the equivalent phi // of ops form. const Expression * NewGVN::makePossiblePhiOfOps(Instruction *I, SmallPtrSetImpl &Visited) { if (!okayForPHIOfOps(I)) return nullptr; if (!Visited.insert(I).second) return nullptr; // For now, we require the instruction be cycle free because we don't // *always* create a phi of ops for instructions that could be done as phi // of ops, we only do it if we think it is useful. If we did do it all the // time, we could remove the cycle free check. if (!isCycleFree(I)) return nullptr; unsigned IDFSNum = InstrToDFSNum(I); SmallPtrSet ProcessedPHIs; // TODO: We don't do phi translation on memory accesses because it's // complicated. For a load, we'd need to be able to simulate a new memoryuse, // which we don't have a good way of doing ATM. auto *MemAccess = getMemoryAccess(I); // If the memory operation is defined by a memory operation this block that // isn't a MemoryPhi, transforming the pointer backwards through a scalar phi // can't help, as it would still be killed by that memory operation. if (MemAccess && !isa(MemAccess->getDefiningAccess()) && MemAccess->getDefiningAccess()->getBlock() == I->getParent()) return nullptr; // Convert op of phis to phi of ops for (auto &Op : I->operands()) { // TODO: We can't handle expressions that must be recursively translated // IE // a = phi (b, c) // f = use a // g = f + phi of something // To properly make a phi of ops for g, we'd have to properly translate and // use the instruction for f. We should add this by splitting out the // instruction creation we do below. if (isa(Op) && PHINodeUses.count(cast(Op))) return nullptr; if (!isa(Op)) continue; auto *OpPHI = cast(Op); // No point in doing this for one-operand phis. if (OpPHI->getNumOperands() == 1) continue; if (!DebugCounter::shouldExecute(PHIOfOpsCounter)) return nullptr; SmallVector, 4> Ops; auto *PHIBlock = getBlockForValue(OpPHI); for (auto PredBB : OpPHI->blocks()) { Value *FoundVal = nullptr; // We could just skip unreachable edges entirely but it's tricky to do // with rewriting existing phi nodes. if (ReachableEdges.count({PredBB, PHIBlock})) { // Clone the instruction, create an expression from it, and see if we // have a leader. Instruction *ValueOp = I->clone(); if (MemAccess) TempToMemory.insert({ValueOp, MemAccess}); for (auto &Op : ValueOp->operands()) { Op = Op->DoPHITranslation(PHIBlock, PredBB); // When this operand changes, it could change whether there is a // leader for us or not. addAdditionalUsers(Op, I); } // Make sure it's marked as a temporary instruction. AllTempInstructions.insert(ValueOp); // and make sure anything that tries to add it's DFS number is // redirected to the instruction we are making a phi of ops // for. InstrDFS.insert({ValueOp, IDFSNum}); const Expression *E = performSymbolicEvaluation(ValueOp, Visited); InstrDFS.erase(ValueOp); AllTempInstructions.erase(ValueOp); ValueOp->deleteValue(); if (MemAccess) TempToMemory.erase(ValueOp); if (!E) return nullptr; FoundVal = findPhiOfOpsLeader(E, PredBB); if (!FoundVal) { ExpressionToPhiOfOps[E].insert(I); return nullptr; } if (auto *SI = dyn_cast(FoundVal)) FoundVal = SI->getValueOperand(); } else { DEBUG(dbgs() << "Skipping phi of ops operand for incoming block " << getBlockName(PredBB) << " because the block is unreachable\n"); FoundVal = UndefValue::get(I->getType()); } Ops.push_back({FoundVal, PredBB}); DEBUG(dbgs() << "Found phi of ops operand " << *FoundVal << " in " << getBlockName(PredBB) << "\n"); } auto *ValuePHI = RealToTemp.lookup(I); bool NewPHI = false; if (!ValuePHI) { ValuePHI = PHINode::Create(I->getType(), OpPHI->getNumOperands()); addPhiOfOps(ValuePHI, PHIBlock, I); NewPHI = true; NumGVNPHIOfOpsCreated++; } if (NewPHI) { for (auto PHIOp : Ops) ValuePHI->addIncoming(PHIOp.first, PHIOp.second); } else { unsigned int i = 0; for (auto PHIOp : Ops) { ValuePHI->setIncomingValue(i, PHIOp.first); ValuePHI->setIncomingBlock(i, PHIOp.second); ++i; } } DEBUG(dbgs() << "Created phi of ops " << *ValuePHI << " for " << *I << "\n"); return performSymbolicEvaluation(ValuePHI, Visited); } return nullptr; } // The algorithm initially places the values of the routine in the TOP // congruence class. The leader of TOP is the undetermined value `undef`. // When the algorithm has finished, values still in TOP are unreachable. void NewGVN::initializeCongruenceClasses(Function &F) { NextCongruenceNum = 0; // Note that even though we use the live on entry def as a representative // MemoryAccess, it is *not* the same as the actual live on entry def. We // have no real equivalemnt to undef for MemoryAccesses, and so we really // should be checking whether the MemoryAccess is top if we want to know if it // is equivalent to everything. Otherwise, what this really signifies is that // the access "it reaches all the way back to the beginning of the function" // Initialize all other instructions to be in TOP class. TOPClass = createCongruenceClass(nullptr, nullptr); TOPClass->setMemoryLeader(MSSA->getLiveOnEntryDef()); // The live on entry def gets put into it's own class MemoryAccessToClass[MSSA->getLiveOnEntryDef()] = createMemoryClass(MSSA->getLiveOnEntryDef()); for (auto DTN : nodes(DT)) { BasicBlock *BB = DTN->getBlock(); // All MemoryAccesses are equivalent to live on entry to start. They must // be initialized to something so that initial changes are noticed. For // the maximal answer, we initialize them all to be the same as // liveOnEntry. auto *MemoryBlockDefs = MSSA->getBlockDefs(BB); if (MemoryBlockDefs) for (const auto &Def : *MemoryBlockDefs) { MemoryAccessToClass[&Def] = TOPClass; auto *MD = dyn_cast(&Def); // Insert the memory phis into the member list. if (!MD) { const MemoryPhi *MP = cast(&Def); TOPClass->memory_insert(MP); MemoryPhiState.insert({MP, MPS_TOP}); } if (MD && isa(MD->getMemoryInst())) TOPClass->incStoreCount(); } for (auto &I : *BB) { // TODO: Move to helper if (isa(&I)) for (auto *U : I.users()) if (auto *UInst = dyn_cast(U)) if (InstrToDFSNum(UInst) != 0 && okayForPHIOfOps(UInst)) PHINodeUses.insert(UInst); // Don't insert void terminators into the class. We don't value number // them, and they just end up sitting in TOP. if (isa(I) && I.getType()->isVoidTy()) continue; TOPClass->insert(&I); ValueToClass[&I] = TOPClass; } } // Initialize arguments to be in their own unique congruence classes for (auto &FA : F.args()) createSingletonCongruenceClass(&FA); } void NewGVN::cleanupTables() { for (unsigned i = 0, e = CongruenceClasses.size(); i != e; ++i) { DEBUG(dbgs() << "Congruence class " << CongruenceClasses[i]->getID() << " has " << CongruenceClasses[i]->size() << " members\n"); // Make sure we delete the congruence class (probably worth switching to // a unique_ptr at some point. delete CongruenceClasses[i]; CongruenceClasses[i] = nullptr; } // Destroy the value expressions SmallVector TempInst(AllTempInstructions.begin(), AllTempInstructions.end()); AllTempInstructions.clear(); // We have to drop all references for everything first, so there are no uses // left as we delete them. for (auto *I : TempInst) { I->dropAllReferences(); } while (!TempInst.empty()) { auto *I = TempInst.back(); TempInst.pop_back(); I->deleteValue(); } ValueToClass.clear(); ArgRecycler.clear(ExpressionAllocator); ExpressionAllocator.Reset(); CongruenceClasses.clear(); ExpressionToClass.clear(); ValueToExpression.clear(); RealToTemp.clear(); AdditionalUsers.clear(); ExpressionToPhiOfOps.clear(); TempToBlock.clear(); TempToMemory.clear(); PHIOfOpsPHIs.clear(); ReachableBlocks.clear(); ReachableEdges.clear(); #ifndef NDEBUG ProcessedCount.clear(); #endif InstrDFS.clear(); InstructionsToErase.clear(); DFSToInstr.clear(); BlockInstRange.clear(); TouchedInstructions.clear(); MemoryAccessToClass.clear(); PredicateToUsers.clear(); MemoryToUsers.clear(); } // Assign local DFS number mapping to instructions, and leave space for Value // PHI's. std::pair NewGVN::assignDFSNumbers(BasicBlock *B, unsigned Start) { unsigned End = Start; if (MemoryAccess *MemPhi = getMemoryAccess(B)) { InstrDFS[MemPhi] = End++; DFSToInstr.emplace_back(MemPhi); } // Then the real block goes next. for (auto &I : *B) { // There's no need to call isInstructionTriviallyDead more than once on // an instruction. Therefore, once we know that an instruction is dead // we change its DFS number so that it doesn't get value numbered. if (isInstructionTriviallyDead(&I, TLI)) { InstrDFS[&I] = 0; DEBUG(dbgs() << "Skipping trivially dead instruction " << I << "\n"); markInstructionForDeletion(&I); continue; } InstrDFS[&I] = End++; DFSToInstr.emplace_back(&I); } // All of the range functions taken half-open ranges (open on the end side). // So we do not subtract one from count, because at this point it is one // greater than the last instruction. return std::make_pair(Start, End); } void NewGVN::updateProcessedCount(const Value *V) { #ifndef NDEBUG if (ProcessedCount.count(V) == 0) { ProcessedCount.insert({V, 1}); } else { ++ProcessedCount[V]; assert(ProcessedCount[V] < 100 && "Seem to have processed the same Value a lot"); } #endif } // Evaluate MemoryPhi nodes symbolically, just like PHI nodes void NewGVN::valueNumberMemoryPhi(MemoryPhi *MP) { // If all the arguments are the same, the MemoryPhi has the same value as the // argument. Filter out unreachable blocks and self phis from our operands. // TODO: We could do cycle-checking on the memory phis to allow valueizing for // self-phi checking. const BasicBlock *PHIBlock = MP->getBlock(); auto Filtered = make_filter_range(MP->operands(), [&](const Use &U) { return cast(U) != MP && !isMemoryAccessTOP(cast(U)) && ReachableEdges.count({MP->getIncomingBlock(U), PHIBlock}); }); // If all that is left is nothing, our memoryphi is undef. We keep it as // InitialClass. Note: The only case this should happen is if we have at // least one self-argument. if (Filtered.begin() == Filtered.end()) { if (setMemoryClass(MP, TOPClass)) markMemoryUsersTouched(MP); return; } // Transform the remaining operands into operand leaders. // FIXME: mapped_iterator should have a range version. auto LookupFunc = [&](const Use &U) { return lookupMemoryLeader(cast(U)); }; auto MappedBegin = map_iterator(Filtered.begin(), LookupFunc); auto MappedEnd = map_iterator(Filtered.end(), LookupFunc); // and now check if all the elements are equal. // Sadly, we can't use std::equals since these are random access iterators. const auto *AllSameValue = *MappedBegin; ++MappedBegin; bool AllEqual = std::all_of( MappedBegin, MappedEnd, [&AllSameValue](const MemoryAccess *V) { return V == AllSameValue; }); if (AllEqual) DEBUG(dbgs() << "Memory Phi value numbered to " << *AllSameValue << "\n"); else DEBUG(dbgs() << "Memory Phi value numbered to itself\n"); // If it's equal to something, it's in that class. Otherwise, it has to be in // a class where it is the leader (other things may be equivalent to it, but // it needs to start off in its own class, which means it must have been the // leader, and it can't have stopped being the leader because it was never // removed). CongruenceClass *CC = AllEqual ? getMemoryClass(AllSameValue) : ensureLeaderOfMemoryClass(MP); auto OldState = MemoryPhiState.lookup(MP); assert(OldState != MPS_Invalid && "Invalid memory phi state"); auto NewState = AllEqual ? MPS_Equivalent : MPS_Unique; MemoryPhiState[MP] = NewState; if (setMemoryClass(MP, CC) || OldState != NewState) markMemoryUsersTouched(MP); } // Value number a single instruction, symbolically evaluating, performing // congruence finding, and updating mappings. void NewGVN::valueNumberInstruction(Instruction *I) { DEBUG(dbgs() << "Processing instruction " << *I << "\n"); if (!I->isTerminator()) { const Expression *Symbolized = nullptr; SmallPtrSet Visited; if (DebugCounter::shouldExecute(VNCounter)) { Symbolized = performSymbolicEvaluation(I, Visited); // Make a phi of ops if necessary if (Symbolized && !isa(Symbolized) && !isa(Symbolized) && PHINodeUses.count(I)) { auto *PHIE = makePossiblePhiOfOps(I, Visited); if (PHIE) Symbolized = PHIE; } } else { // Mark the instruction as unused so we don't value number it again. InstrDFS[I] = 0; } // If we couldn't come up with a symbolic expression, use the unknown // expression if (Symbolized == nullptr) Symbolized = createUnknownExpression(I); performCongruenceFinding(I, Symbolized); } else { // Handle terminators that return values. All of them produce values we // don't currently understand. We don't place non-value producing // terminators in a class. if (!I->getType()->isVoidTy()) { auto *Symbolized = createUnknownExpression(I); performCongruenceFinding(I, Symbolized); } processOutgoingEdges(dyn_cast(I), I->getParent()); } } // Check if there is a path, using single or equal argument phi nodes, from // First to Second. bool NewGVN::singleReachablePHIPath( SmallPtrSet &Visited, const MemoryAccess *First, const MemoryAccess *Second) const { if (First == Second) return true; if (MSSA->isLiveOnEntryDef(First)) return false; // This is not perfect, but as we're just verifying here, we can live with // the loss of precision. The real solution would be that of doing strongly // connected component finding in this routine, and it's probably not worth // the complexity for the time being. So, we just keep a set of visited // MemoryAccess and return true when we hit a cycle. if (Visited.count(First)) return true; Visited.insert(First); const auto *EndDef = First; for (auto *ChainDef : optimized_def_chain(First)) { if (ChainDef == Second) return true; if (MSSA->isLiveOnEntryDef(ChainDef)) return false; EndDef = ChainDef; } auto *MP = cast(EndDef); auto ReachableOperandPred = [&](const Use &U) { return ReachableEdges.count({MP->getIncomingBlock(U), MP->getBlock()}); }; auto FilteredPhiArgs = make_filter_range(MP->operands(), ReachableOperandPred); SmallVector OperandList; std::copy(FilteredPhiArgs.begin(), FilteredPhiArgs.end(), std::back_inserter(OperandList)); bool Okay = OperandList.size() == 1; if (!Okay) Okay = std::equal(OperandList.begin(), OperandList.end(), OperandList.begin()); if (Okay) return singleReachablePHIPath(Visited, cast(OperandList[0]), Second); return false; } // Verify the that the memory equivalence table makes sense relative to the // congruence classes. Note that this checking is not perfect, and is currently // subject to very rare false negatives. It is only useful for // testing/debugging. void NewGVN::verifyMemoryCongruency() const { #ifndef NDEBUG // Verify that the memory table equivalence and memory member set match for (const auto *CC : CongruenceClasses) { if (CC == TOPClass || CC->isDead()) continue; if (CC->getStoreCount() != 0) { assert((CC->getStoredValue() || !isa(CC->getLeader())) && "Any class with a store as a leader should have a " "representative stored value"); assert(CC->getMemoryLeader() && "Any congruence class with a store should have a " "representative access"); } if (CC->getMemoryLeader()) assert(MemoryAccessToClass.lookup(CC->getMemoryLeader()) == CC && "Representative MemoryAccess does not appear to be reverse " "mapped properly"); for (auto M : CC->memory()) assert(MemoryAccessToClass.lookup(M) == CC && "Memory member does not appear to be reverse mapped properly"); } // Anything equivalent in the MemoryAccess table should be in the same // congruence class. // Filter out the unreachable and trivially dead entries, because they may // never have been updated if the instructions were not processed. auto ReachableAccessPred = [&](const std::pair Pair) { bool Result = ReachableBlocks.count(Pair.first->getBlock()); if (!Result || MSSA->isLiveOnEntryDef(Pair.first) || MemoryToDFSNum(Pair.first) == 0) return false; if (auto *MemDef = dyn_cast(Pair.first)) return !isInstructionTriviallyDead(MemDef->getMemoryInst()); // We could have phi nodes which operands are all trivially dead, // so we don't process them. if (auto *MemPHI = dyn_cast(Pair.first)) { for (auto &U : MemPHI->incoming_values()) { if (Instruction *I = dyn_cast(U.get())) { if (!isInstructionTriviallyDead(I)) return true; } } return false; } return true; }; auto Filtered = make_filter_range(MemoryAccessToClass, ReachableAccessPred); for (auto KV : Filtered) { if (auto *FirstMUD = dyn_cast(KV.first)) { auto *SecondMUD = dyn_cast(KV.second->getMemoryLeader()); if (FirstMUD && SecondMUD) { SmallPtrSet VisitedMAS; assert((singleReachablePHIPath(VisitedMAS, FirstMUD, SecondMUD) || ValueToClass.lookup(FirstMUD->getMemoryInst()) == ValueToClass.lookup(SecondMUD->getMemoryInst())) && "The instructions for these memory operations should have " "been in the same congruence class or reachable through" "a single argument phi"); } } else if (auto *FirstMP = dyn_cast(KV.first)) { // We can only sanely verify that MemoryDefs in the operand list all have // the same class. auto ReachableOperandPred = [&](const Use &U) { return ReachableEdges.count( {FirstMP->getIncomingBlock(U), FirstMP->getBlock()}) && isa(U); }; // All arguments should in the same class, ignoring unreachable arguments auto FilteredPhiArgs = make_filter_range(FirstMP->operands(), ReachableOperandPred); SmallVector PhiOpClasses; std::transform(FilteredPhiArgs.begin(), FilteredPhiArgs.end(), std::back_inserter(PhiOpClasses), [&](const Use &U) { const MemoryDef *MD = cast(U); return ValueToClass.lookup(MD->getMemoryInst()); }); assert(std::equal(PhiOpClasses.begin(), PhiOpClasses.end(), PhiOpClasses.begin()) && "All MemoryPhi arguments should be in the same class"); } } #endif } // Verify that the sparse propagation we did actually found the maximal fixpoint // We do this by storing the value to class mapping, touching all instructions, // and redoing the iteration to see if anything changed. void NewGVN::verifyIterationSettled(Function &F) { #ifndef NDEBUG DEBUG(dbgs() << "Beginning iteration verification\n"); if (DebugCounter::isCounterSet(VNCounter)) DebugCounter::setCounterValue(VNCounter, StartingVNCounter); // Note that we have to store the actual classes, as we may change existing // classes during iteration. This is because our memory iteration propagation // is not perfect, and so may waste a little work. But it should generate // exactly the same congruence classes we have now, with different IDs. std::map BeforeIteration; for (auto &KV : ValueToClass) { if (auto *I = dyn_cast(KV.first)) // Skip unused/dead instructions. if (InstrToDFSNum(I) == 0) continue; BeforeIteration.insert({KV.first, *KV.second}); } TouchedInstructions.set(); TouchedInstructions.reset(0); iterateTouchedInstructions(); DenseSet> EqualClasses; for (const auto &KV : ValueToClass) { if (auto *I = dyn_cast(KV.first)) // Skip unused/dead instructions. if (InstrToDFSNum(I) == 0) continue; // We could sink these uses, but i think this adds a bit of clarity here as // to what we are comparing. auto *BeforeCC = &BeforeIteration.find(KV.first)->second; auto *AfterCC = KV.second; // Note that the classes can't change at this point, so we memoize the set // that are equal. if (!EqualClasses.count({BeforeCC, AfterCC})) { assert(BeforeCC->isEquivalentTo(AfterCC) && "Value number changed after main loop completed!"); EqualClasses.insert({BeforeCC, AfterCC}); } } #endif } // Verify that for each store expression in the expression to class mapping, // only the latest appears, and multiple ones do not appear. // Because loads do not use the stored value when doing equality with stores, // if we don't erase the old store expressions from the table, a load can find // a no-longer valid StoreExpression. void NewGVN::verifyStoreExpressions() const { #ifndef NDEBUG // This is the only use of this, and it's not worth defining a complicated // densemapinfo hash/equality function for it. std::set< std::pair>> StoreExpressionSet; for (const auto &KV : ExpressionToClass) { if (auto *SE = dyn_cast(KV.first)) { // Make sure a version that will conflict with loads is not already there auto Res = StoreExpressionSet.insert( {SE->getOperand(0), std::make_tuple(SE->getMemoryLeader(), KV.second, SE->getStoredValue())}); bool Okay = Res.second; // It's okay to have the same expression already in there if it is // identical in nature. // This can happen when the leader of the stored value changes over time. if (!Okay) Okay = (std::get<1>(Res.first->second) == KV.second) && (lookupOperandLeader(std::get<2>(Res.first->second)) == lookupOperandLeader(SE->getStoredValue())); assert(Okay && "Stored expression conflict exists in expression table"); auto *ValueExpr = ValueToExpression.lookup(SE->getStoreInst()); assert(ValueExpr && ValueExpr->equals(*SE) && "StoreExpression in ExpressionToClass is not latest " "StoreExpression for value"); } } #endif } // This is the main value numbering loop, it iterates over the initial touched // instruction set, propagating value numbers, marking things touched, etc, // until the set of touched instructions is completely empty. void NewGVN::iterateTouchedInstructions() { unsigned int Iterations = 0; // Figure out where touchedinstructions starts int FirstInstr = TouchedInstructions.find_first(); // Nothing set, nothing to iterate, just return. if (FirstInstr == -1) return; const BasicBlock *LastBlock = getBlockForValue(InstrFromDFSNum(FirstInstr)); while (TouchedInstructions.any()) { ++Iterations; // Walk through all the instructions in all the blocks in RPO. // TODO: As we hit a new block, we should push and pop equalities into a // table lookupOperandLeader can use, to catch things PredicateInfo // might miss, like edge-only equivalences. for (unsigned InstrNum : TouchedInstructions.set_bits()) { // This instruction was found to be dead. We don't bother looking // at it again. if (InstrNum == 0) { TouchedInstructions.reset(InstrNum); continue; } Value *V = InstrFromDFSNum(InstrNum); const BasicBlock *CurrBlock = getBlockForValue(V); // If we hit a new block, do reachability processing. if (CurrBlock != LastBlock) { LastBlock = CurrBlock; bool BlockReachable = ReachableBlocks.count(CurrBlock); const auto &CurrInstRange = BlockInstRange.lookup(CurrBlock); // If it's not reachable, erase any touched instructions and move on. if (!BlockReachable) { TouchedInstructions.reset(CurrInstRange.first, CurrInstRange.second); DEBUG(dbgs() << "Skipping instructions in block " << getBlockName(CurrBlock) << " because it is unreachable\n"); continue; } updateProcessedCount(CurrBlock); } // Reset after processing (because we may mark ourselves as touched when // we propagate equalities). TouchedInstructions.reset(InstrNum); if (auto *MP = dyn_cast(V)) { DEBUG(dbgs() << "Processing MemoryPhi " << *MP << "\n"); valueNumberMemoryPhi(MP); } else if (auto *I = dyn_cast(V)) { valueNumberInstruction(I); } else { llvm_unreachable("Should have been a MemoryPhi or Instruction"); } updateProcessedCount(V); } } NumGVNMaxIterations = std::max(NumGVNMaxIterations.getValue(), Iterations); } // This is the main transformation entry point. bool NewGVN::runGVN() { if (DebugCounter::isCounterSet(VNCounter)) StartingVNCounter = DebugCounter::getCounterValue(VNCounter); bool Changed = false; NumFuncArgs = F.arg_size(); MSSAWalker = MSSA->getWalker(); SingletonDeadExpression = new (ExpressionAllocator) DeadExpression(); // Count number of instructions for sizing of hash tables, and come // up with a global dfs numbering for instructions. unsigned ICount = 1; // Add an empty instruction to account for the fact that we start at 1 DFSToInstr.emplace_back(nullptr); // Note: We want ideal RPO traversal of the blocks, which is not quite the // same as dominator tree order, particularly with regard whether backedges // get visited first or second, given a block with multiple successors. // If we visit in the wrong order, we will end up performing N times as many // iterations. // The dominator tree does guarantee that, for a given dom tree node, it's // parent must occur before it in the RPO ordering. Thus, we only need to sort // the siblings. ReversePostOrderTraversal RPOT(&F); unsigned Counter = 0; for (auto &B : RPOT) { auto *Node = DT->getNode(B); assert(Node && "RPO and Dominator tree should have same reachability"); RPOOrdering[Node] = ++Counter; } // Sort dominator tree children arrays into RPO. for (auto &B : RPOT) { auto *Node = DT->getNode(B); if (Node->getChildren().size() > 1) std::sort(Node->begin(), Node->end(), [&](const DomTreeNode *A, const DomTreeNode *B) { return RPOOrdering[A] < RPOOrdering[B]; }); } // Now a standard depth first ordering of the domtree is equivalent to RPO. for (auto DTN : depth_first(DT->getRootNode())) { BasicBlock *B = DTN->getBlock(); const auto &BlockRange = assignDFSNumbers(B, ICount); BlockInstRange.insert({B, BlockRange}); ICount += BlockRange.second - BlockRange.first; } initializeCongruenceClasses(F); TouchedInstructions.resize(ICount); // Ensure we don't end up resizing the expressionToClass map, as // that can be quite expensive. At most, we have one expression per // instruction. ExpressionToClass.reserve(ICount); // Initialize the touched instructions to include the entry block. const auto &InstRange = BlockInstRange.lookup(&F.getEntryBlock()); TouchedInstructions.set(InstRange.first, InstRange.second); DEBUG(dbgs() << "Block " << getBlockName(&F.getEntryBlock()) << " marked reachable\n"); ReachableBlocks.insert(&F.getEntryBlock()); iterateTouchedInstructions(); verifyMemoryCongruency(); verifyIterationSettled(F); verifyStoreExpressions(); Changed |= eliminateInstructions(F); // Delete all instructions marked for deletion. for (Instruction *ToErase : InstructionsToErase) { if (!ToErase->use_empty()) ToErase->replaceAllUsesWith(UndefValue::get(ToErase->getType())); if (ToErase->getParent()) ToErase->eraseFromParent(); } // Delete all unreachable blocks. auto UnreachableBlockPred = [&](const BasicBlock &BB) { return !ReachableBlocks.count(&BB); }; for (auto &BB : make_filter_range(F, UnreachableBlockPred)) { DEBUG(dbgs() << "We believe block " << getBlockName(&BB) << " is unreachable\n"); deleteInstructionsInBlock(&BB); Changed = true; } cleanupTables(); return Changed; } struct NewGVN::ValueDFS { int DFSIn = 0; int DFSOut = 0; int LocalNum = 0; // Only one of Def and U will be set. // The bool in the Def tells us whether the Def is the stored value of a // store. PointerIntPair Def; Use *U = nullptr; bool operator<(const ValueDFS &Other) const { // It's not enough that any given field be less than - we have sets // of fields that need to be evaluated together to give a proper ordering. // For example, if you have; // DFS (1, 3) // Val 0 // DFS (1, 2) // Val 50 // We want the second to be less than the first, but if we just go field // by field, we will get to Val 0 < Val 50 and say the first is less than // the second. We only want it to be less than if the DFS orders are equal. // // Each LLVM instruction only produces one value, and thus the lowest-level // differentiator that really matters for the stack (and what we use as as a // replacement) is the local dfs number. // Everything else in the structure is instruction level, and only affects // the order in which we will replace operands of a given instruction. // // For a given instruction (IE things with equal dfsin, dfsout, localnum), // the order of replacement of uses does not matter. // IE given, // a = 5 // b = a + a // When you hit b, you will have two valuedfs with the same dfsin, out, and // localnum. // The .val will be the same as well. // The .u's will be different. // You will replace both, and it does not matter what order you replace them // in (IE whether you replace operand 2, then operand 1, or operand 1, then // operand 2). // Similarly for the case of same dfsin, dfsout, localnum, but different // .val's // a = 5 // b = 6 // c = a + b // in c, we will a valuedfs for a, and one for b,with everything the same // but .val and .u. // It does not matter what order we replace these operands in. // You will always end up with the same IR, and this is guaranteed. return std::tie(DFSIn, DFSOut, LocalNum, Def, U) < std::tie(Other.DFSIn, Other.DFSOut, Other.LocalNum, Other.Def, Other.U); } }; // This function converts the set of members for a congruence class from values, // to sets of defs and uses with associated DFS info. The total number of // reachable uses for each value is stored in UseCount, and instructions that // seem // dead (have no non-dead uses) are stored in ProbablyDead. void NewGVN::convertClassToDFSOrdered( const CongruenceClass &Dense, SmallVectorImpl &DFSOrderedSet, DenseMap &UseCounts, SmallPtrSetImpl &ProbablyDead) const { for (auto D : Dense) { // First add the value. BasicBlock *BB = getBlockForValue(D); // Constants are handled prior to ever calling this function, so // we should only be left with instructions as members. assert(BB && "Should have figured out a basic block for value"); ValueDFS VDDef; DomTreeNode *DomNode = DT->getNode(BB); VDDef.DFSIn = DomNode->getDFSNumIn(); VDDef.DFSOut = DomNode->getDFSNumOut(); // If it's a store, use the leader of the value operand, if it's always // available, or the value operand. TODO: We could do dominance checks to // find a dominating leader, but not worth it ATM. if (auto *SI = dyn_cast(D)) { auto Leader = lookupOperandLeader(SI->getValueOperand()); if (alwaysAvailable(Leader)) { VDDef.Def.setPointer(Leader); } else { VDDef.Def.setPointer(SI->getValueOperand()); VDDef.Def.setInt(true); } } else { VDDef.Def.setPointer(D); } assert(isa(D) && "The dense set member should always be an instruction"); Instruction *Def = cast(D); VDDef.LocalNum = InstrToDFSNum(D); DFSOrderedSet.push_back(VDDef); // If there is a phi node equivalent, add it if (auto *PN = RealToTemp.lookup(Def)) { auto *PHIE = dyn_cast_or_null(ValueToExpression.lookup(Def)); if (PHIE) { VDDef.Def.setInt(false); VDDef.Def.setPointer(PN); VDDef.LocalNum = 0; DFSOrderedSet.push_back(VDDef); } } unsigned int UseCount = 0; // Now add the uses. for (auto &U : Def->uses()) { if (auto *I = dyn_cast(U.getUser())) { // Don't try to replace into dead uses if (InstructionsToErase.count(I)) continue; ValueDFS VDUse; // Put the phi node uses in the incoming block. BasicBlock *IBlock; if (auto *P = dyn_cast(I)) { IBlock = P->getIncomingBlock(U); // Make phi node users appear last in the incoming block // they are from. VDUse.LocalNum = InstrDFS.size() + 1; } else { IBlock = getBlockForValue(I); VDUse.LocalNum = InstrToDFSNum(I); } // Skip uses in unreachable blocks, as we're going // to delete them. if (ReachableBlocks.count(IBlock) == 0) continue; DomTreeNode *DomNode = DT->getNode(IBlock); VDUse.DFSIn = DomNode->getDFSNumIn(); VDUse.DFSOut = DomNode->getDFSNumOut(); VDUse.U = &U; ++UseCount; DFSOrderedSet.emplace_back(VDUse); } } // If there are no uses, it's probably dead (but it may have side-effects, // so not definitely dead. Otherwise, store the number of uses so we can // track if it becomes dead later). if (UseCount == 0) ProbablyDead.insert(Def); else UseCounts[Def] = UseCount; } } // This function converts the set of members for a congruence class from values, // to the set of defs for loads and stores, with associated DFS info. void NewGVN::convertClassToLoadsAndStores( const CongruenceClass &Dense, SmallVectorImpl &LoadsAndStores) const { for (auto D : Dense) { if (!isa(D) && !isa(D)) continue; BasicBlock *BB = getBlockForValue(D); ValueDFS VD; DomTreeNode *DomNode = DT->getNode(BB); VD.DFSIn = DomNode->getDFSNumIn(); VD.DFSOut = DomNode->getDFSNumOut(); VD.Def.setPointer(D); // If it's an instruction, use the real local dfs number. if (auto *I = dyn_cast(D)) VD.LocalNum = InstrToDFSNum(I); else llvm_unreachable("Should have been an instruction"); LoadsAndStores.emplace_back(VD); } } static void patchReplacementInstruction(Instruction *I, Value *Repl) { auto *ReplInst = dyn_cast(Repl); if (!ReplInst) return; // Patch the replacement so that it is not more restrictive than the value // being replaced. // Note that if 'I' is a load being replaced by some operation, // for example, by an arithmetic operation, then andIRFlags() // would just erase all math flags from the original arithmetic // operation, which is clearly not wanted and not needed. if (!isa(I)) ReplInst->andIRFlags(I); // FIXME: If both the original and replacement value are part of the // same control-flow region (meaning that the execution of one // guarantees the execution of the other), then we can combine the // noalias scopes here and do better than the general conservative // answer used in combineMetadata(). // In general, GVN unifies expressions over different control-flow // regions, and so we need a conservative combination of the noalias // scopes. static const unsigned KnownIDs[] = { LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope, LLVMContext::MD_noalias, LLVMContext::MD_range, LLVMContext::MD_fpmath, LLVMContext::MD_invariant_load, LLVMContext::MD_invariant_group}; combineMetadata(ReplInst, I, KnownIDs); } static void patchAndReplaceAllUsesWith(Instruction *I, Value *Repl) { patchReplacementInstruction(I, Repl); I->replaceAllUsesWith(Repl); } void NewGVN::deleteInstructionsInBlock(BasicBlock *BB) { DEBUG(dbgs() << " BasicBlock Dead:" << *BB); ++NumGVNBlocksDeleted; // Delete the instructions backwards, as it has a reduced likelihood of having // to update as many def-use and use-def chains. Start after the terminator. auto StartPoint = BB->rbegin(); ++StartPoint; // Note that we explicitly recalculate BB->rend() on each iteration, // as it may change when we remove the first instruction. for (BasicBlock::reverse_iterator I(StartPoint); I != BB->rend();) { Instruction &Inst = *I++; if (!Inst.use_empty()) Inst.replaceAllUsesWith(UndefValue::get(Inst.getType())); if (isa(Inst)) continue; Inst.eraseFromParent(); ++NumGVNInstrDeleted; } // Now insert something that simplifycfg will turn into an unreachable. Type *Int8Ty = Type::getInt8Ty(BB->getContext()); new StoreInst(UndefValue::get(Int8Ty), Constant::getNullValue(Int8Ty->getPointerTo()), BB->getTerminator()); } void NewGVN::markInstructionForDeletion(Instruction *I) { DEBUG(dbgs() << "Marking " << *I << " for deletion\n"); InstructionsToErase.insert(I); } void NewGVN::replaceInstruction(Instruction *I, Value *V) { DEBUG(dbgs() << "Replacing " << *I << " with " << *V << "\n"); patchAndReplaceAllUsesWith(I, V); // We save the actual erasing to avoid invalidating memory // dependencies until we are done with everything. markInstructionForDeletion(I); } namespace { // This is a stack that contains both the value and dfs info of where // that value is valid. class ValueDFSStack { public: Value *back() const { return ValueStack.back(); } std::pair dfs_back() const { return DFSStack.back(); } void push_back(Value *V, int DFSIn, int DFSOut) { ValueStack.emplace_back(V); DFSStack.emplace_back(DFSIn, DFSOut); } bool empty() const { return DFSStack.empty(); } bool isInScope(int DFSIn, int DFSOut) const { if (empty()) return false; return DFSIn >= DFSStack.back().first && DFSOut <= DFSStack.back().second; } void popUntilDFSScope(int DFSIn, int DFSOut) { // These two should always be in sync at this point. assert(ValueStack.size() == DFSStack.size() && "Mismatch between ValueStack and DFSStack"); while ( !DFSStack.empty() && !(DFSIn >= DFSStack.back().first && DFSOut <= DFSStack.back().second)) { DFSStack.pop_back(); ValueStack.pop_back(); } } private: SmallVector ValueStack; SmallVector, 8> DFSStack; }; } // Given a value and a basic block we are trying to see if it is available in, // see if the value has a leader available in that block. Value *NewGVN::findPhiOfOpsLeader(const Expression *E, const BasicBlock *BB) const { // It would already be constant if we could make it constant if (auto *CE = dyn_cast(E)) return CE->getConstantValue(); if (auto *VE = dyn_cast(E)) return VE->getVariableValue(); auto *CC = ExpressionToClass.lookup(E); if (!CC) return nullptr; if (alwaysAvailable(CC->getLeader())) return CC->getLeader(); for (auto Member : *CC) { auto *MemberInst = dyn_cast(Member); // Anything that isn't an instruction is always available. if (!MemberInst) return Member; // If we are looking for something in the same block as the member, it must // be a leader because this function is looking for operands for a phi node. if (MemberInst->getParent() == BB || DT->dominates(MemberInst->getParent(), BB)) { return Member; } } return nullptr; } bool NewGVN::eliminateInstructions(Function &F) { // This is a non-standard eliminator. The normal way to eliminate is // to walk the dominator tree in order, keeping track of available // values, and eliminating them. However, this is mildly // pointless. It requires doing lookups on every instruction, // regardless of whether we will ever eliminate it. For // instructions part of most singleton congruence classes, we know we // will never eliminate them. // Instead, this eliminator looks at the congruence classes directly, sorts // them into a DFS ordering of the dominator tree, and then we just // perform elimination straight on the sets by walking the congruence // class member uses in order, and eliminate the ones dominated by the // last member. This is worst case O(E log E) where E = number of // instructions in a single congruence class. In theory, this is all // instructions. In practice, it is much faster, as most instructions are // either in singleton congruence classes or can't possibly be eliminated // anyway (if there are no overlapping DFS ranges in class). // When we find something not dominated, it becomes the new leader // for elimination purposes. // TODO: If we wanted to be faster, We could remove any members with no // overlapping ranges while sorting, as we will never eliminate anything // with those members, as they don't dominate anything else in our set. bool AnythingReplaced = false; // Since we are going to walk the domtree anyway, and we can't guarantee the // DFS numbers are updated, we compute some ourselves. DT->updateDFSNumbers(); // Go through all of our phi nodes, and kill the arguments associated with // unreachable edges. auto ReplaceUnreachablePHIArgs = [&](PHINode &PHI, BasicBlock *BB) { for (auto &Operand : PHI.incoming_values()) if (!ReachableEdges.count({PHI.getIncomingBlock(Operand), BB})) { DEBUG(dbgs() << "Replacing incoming value of " << PHI << " for block " << getBlockName(PHI.getIncomingBlock(Operand)) << " with undef due to it being unreachable\n"); Operand.set(UndefValue::get(PHI.getType())); } }; SmallPtrSet BlocksWithPhis; for (auto &B : F) if ((!B.empty() && isa(*B.begin())) || (PHIOfOpsPHIs.find(&B) != PHIOfOpsPHIs.end())) BlocksWithPhis.insert(&B); DenseMap ReachablePredCount; for (auto KV : ReachableEdges) ReachablePredCount[KV.getEnd()]++; for (auto *BB : BlocksWithPhis) // TODO: It would be faster to use getNumIncomingBlocks() on a phi node in // the block and subtract the pred count, but it's more complicated. if (ReachablePredCount.lookup(BB) != unsigned(std::distance(pred_begin(BB), pred_end(BB)))) { for (auto II = BB->begin(); isa(II); ++II) { auto &PHI = cast(*II); ReplaceUnreachablePHIArgs(PHI, BB); } for_each_found(PHIOfOpsPHIs, BB, [&](PHINode *PHI) { ReplaceUnreachablePHIArgs(*PHI, BB); }); } // Map to store the use counts DenseMap UseCounts; for (auto *CC : reverse(CongruenceClasses)) { DEBUG(dbgs() << "Eliminating in congruence class " << CC->getID() << "\n"); // Track the equivalent store info so we can decide whether to try // dead store elimination. SmallVector PossibleDeadStores; SmallPtrSet ProbablyDead; if (CC->isDead() || CC->empty()) continue; // Everything still in the TOP class is unreachable or dead. if (CC == TOPClass) { for (auto M : *CC) { auto *VTE = ValueToExpression.lookup(M); if (VTE && isa(VTE)) markInstructionForDeletion(cast(M)); assert((!ReachableBlocks.count(cast(M)->getParent()) || InstructionsToErase.count(cast(M))) && "Everything in TOP should be unreachable or dead at this " "point"); } continue; } assert(CC->getLeader() && "We should have had a leader"); // If this is a leader that is always available, and it's a // constant or has no equivalences, just replace everything with // it. We then update the congruence class with whatever members // are left. Value *Leader = CC->getStoredValue() ? CC->getStoredValue() : CC->getLeader(); if (alwaysAvailable(Leader)) { CongruenceClass::MemberSet MembersLeft; for (auto M : *CC) { Value *Member = M; // Void things have no uses we can replace. if (Member == Leader || !isa(Member) || Member->getType()->isVoidTy()) { MembersLeft.insert(Member); continue; } DEBUG(dbgs() << "Found replacement " << *(Leader) << " for " << *Member << "\n"); auto *I = cast(Member); assert(Leader != I && "About to accidentally remove our leader"); replaceInstruction(I, Leader); AnythingReplaced = true; } CC->swap(MembersLeft); } else { // If this is a singleton, we can skip it. if (CC->size() != 1 || RealToTemp.lookup(Leader)) { // This is a stack because equality replacement/etc may place // constants in the middle of the member list, and we want to use // those constant values in preference to the current leader, over // the scope of those constants. ValueDFSStack EliminationStack; // Convert the members to DFS ordered sets and then merge them. SmallVector DFSOrderedSet; convertClassToDFSOrdered(*CC, DFSOrderedSet, UseCounts, ProbablyDead); // Sort the whole thing. std::sort(DFSOrderedSet.begin(), DFSOrderedSet.end()); for (auto &VD : DFSOrderedSet) { int MemberDFSIn = VD.DFSIn; int MemberDFSOut = VD.DFSOut; Value *Def = VD.Def.getPointer(); bool FromStore = VD.Def.getInt(); Use *U = VD.U; // We ignore void things because we can't get a value from them. if (Def && Def->getType()->isVoidTy()) continue; auto *DefInst = dyn_cast_or_null(Def); if (DefInst && AllTempInstructions.count(DefInst)) { auto *PN = cast(DefInst); // If this is a value phi and that's the expression we used, insert // it into the program // remove from temp instruction list. AllTempInstructions.erase(PN); auto *DefBlock = getBlockForValue(Def); DEBUG(dbgs() << "Inserting fully real phi of ops" << *Def << " into block " << getBlockName(getBlockForValue(Def)) << "\n"); PN->insertBefore(&DefBlock->front()); Def = PN; NumGVNPHIOfOpsEliminations++; } if (EliminationStack.empty()) { DEBUG(dbgs() << "Elimination Stack is empty\n"); } else { DEBUG(dbgs() << "Elimination Stack Top DFS numbers are (" << EliminationStack.dfs_back().first << "," << EliminationStack.dfs_back().second << ")\n"); } DEBUG(dbgs() << "Current DFS numbers are (" << MemberDFSIn << "," << MemberDFSOut << ")\n"); // First, we see if we are out of scope or empty. If so, // and there equivalences, we try to replace the top of // stack with equivalences (if it's on the stack, it must // not have been eliminated yet). // Then we synchronize to our current scope, by // popping until we are back within a DFS scope that // dominates the current member. // Then, what happens depends on a few factors // If the stack is now empty, we need to push // If we have a constant or a local equivalence we want to // start using, we also push. // Otherwise, we walk along, processing members who are // dominated by this scope, and eliminate them. bool ShouldPush = Def && EliminationStack.empty(); bool OutOfScope = !EliminationStack.isInScope(MemberDFSIn, MemberDFSOut); if (OutOfScope || ShouldPush) { // Sync to our current scope. EliminationStack.popUntilDFSScope(MemberDFSIn, MemberDFSOut); bool ShouldPush = Def && EliminationStack.empty(); if (ShouldPush) { EliminationStack.push_back(Def, MemberDFSIn, MemberDFSOut); } } // Skip the Def's, we only want to eliminate on their uses. But mark // dominated defs as dead. if (Def) { // For anything in this case, what and how we value number // guarantees that any side-effets that would have occurred (ie // throwing, etc) can be proven to either still occur (because it's // dominated by something that has the same side-effects), or never // occur. Otherwise, we would not have been able to prove it value // equivalent to something else. For these things, we can just mark // it all dead. Note that this is different from the "ProbablyDead" // set, which may not be dominated by anything, and thus, are only // easy to prove dead if they are also side-effect free. Note that // because stores are put in terms of the stored value, we skip // stored values here. If the stored value is really dead, it will // still be marked for deletion when we process it in its own class. if (!EliminationStack.empty() && Def != EliminationStack.back() && isa(Def) && !FromStore) markInstructionForDeletion(cast(Def)); continue; } // At this point, we know it is a Use we are trying to possibly // replace. assert(isa(U->get()) && "Current def should have been an instruction"); assert(isa(U->getUser()) && "Current user should have been an instruction"); // If the thing we are replacing into is already marked to be dead, // this use is dead. Note that this is true regardless of whether // we have anything dominating the use or not. We do this here // because we are already walking all the uses anyway. Instruction *InstUse = cast(U->getUser()); if (InstructionsToErase.count(InstUse)) { auto &UseCount = UseCounts[U->get()]; if (--UseCount == 0) { ProbablyDead.insert(cast(U->get())); } } // If we get to this point, and the stack is empty we must have a use // with nothing we can use to eliminate this use, so just skip it. if (EliminationStack.empty()) continue; Value *DominatingLeader = EliminationStack.back(); auto *II = dyn_cast(DominatingLeader); if (II && II->getIntrinsicID() == Intrinsic::ssa_copy) DominatingLeader = II->getOperand(0); // Don't replace our existing users with ourselves. if (U->get() == DominatingLeader) continue; DEBUG(dbgs() << "Found replacement " << *DominatingLeader << " for " << *U->get() << " in " << *(U->getUser()) << "\n"); // If we replaced something in an instruction, handle the patching of // metadata. Skip this if we are replacing predicateinfo with its // original operand, as we already know we can just drop it. auto *ReplacedInst = cast(U->get()); auto *PI = PredInfo->getPredicateInfoFor(ReplacedInst); if (!PI || DominatingLeader != PI->OriginalOp) patchReplacementInstruction(ReplacedInst, DominatingLeader); U->set(DominatingLeader); // This is now a use of the dominating leader, which means if the // dominating leader was dead, it's now live! auto &LeaderUseCount = UseCounts[DominatingLeader]; // It's about to be alive again. if (LeaderUseCount == 0 && isa(DominatingLeader)) ProbablyDead.erase(cast(DominatingLeader)); if (LeaderUseCount == 0 && II) ProbablyDead.insert(II); ++LeaderUseCount; AnythingReplaced = true; } } } // At this point, anything still in the ProbablyDead set is actually dead if // would be trivially dead. for (auto *I : ProbablyDead) if (wouldInstructionBeTriviallyDead(I)) markInstructionForDeletion(I); // Cleanup the congruence class. CongruenceClass::MemberSet MembersLeft; for (auto *Member : *CC) if (!isa(Member) || !InstructionsToErase.count(cast(Member))) MembersLeft.insert(Member); CC->swap(MembersLeft); // If we have possible dead stores to look at, try to eliminate them. if (CC->getStoreCount() > 0) { convertClassToLoadsAndStores(*CC, PossibleDeadStores); std::sort(PossibleDeadStores.begin(), PossibleDeadStores.end()); ValueDFSStack EliminationStack; for (auto &VD : PossibleDeadStores) { int MemberDFSIn = VD.DFSIn; int MemberDFSOut = VD.DFSOut; Instruction *Member = cast(VD.Def.getPointer()); if (EliminationStack.empty() || !EliminationStack.isInScope(MemberDFSIn, MemberDFSOut)) { // Sync to our current scope. EliminationStack.popUntilDFSScope(MemberDFSIn, MemberDFSOut); if (EliminationStack.empty()) { EliminationStack.push_back(Member, MemberDFSIn, MemberDFSOut); continue; } } // We already did load elimination, so nothing to do here. if (isa(Member)) continue; assert(!EliminationStack.empty()); Instruction *Leader = cast(EliminationStack.back()); (void)Leader; assert(DT->dominates(Leader->getParent(), Member->getParent())); // Member is dominater by Leader, and thus dead DEBUG(dbgs() << "Marking dead store " << *Member << " that is dominated by " << *Leader << "\n"); markInstructionForDeletion(Member); CC->erase(Member); ++NumGVNDeadStores; } } } return AnythingReplaced; } // This function provides global ranking of operations so that we can place them // in a canonical order. Note that rank alone is not necessarily enough for a // complete ordering, as constants all have the same rank. However, generally, // we will simplify an operation with all constants so that it doesn't matter // what order they appear in. unsigned int NewGVN::getRank(const Value *V) const { // Prefer constants to undef to anything else // Undef is a constant, have to check it first. // Prefer smaller constants to constantexprs if (isa(V)) return 2; if (isa(V)) return 1; if (isa(V)) return 0; else if (auto *A = dyn_cast(V)) return 3 + A->getArgNo(); // Need to shift the instruction DFS by number of arguments + 3 to account for // the constant and argument ranking above. unsigned Result = InstrToDFSNum(V); if (Result > 0) return 4 + NumFuncArgs + Result; // Unreachable or something else, just return a really large number. return ~0; } // This is a function that says whether two commutative operations should // have their order swapped when canonicalizing. bool NewGVN::shouldSwapOperands(const Value *A, const Value *B) const { // Because we only care about a total ordering, and don't rewrite expressions // in this order, we order by rank, which will give a strict weak ordering to // everything but constants, and then we order by pointer address. return std::make_pair(getRank(A), A) > std::make_pair(getRank(B), B); } namespace { class NewGVNLegacyPass : public FunctionPass { public: static char ID; // Pass identification, replacement for typeid. NewGVNLegacyPass() : FunctionPass(ID) { initializeNewGVNLegacyPassPass(*PassRegistry::getPassRegistry()); } bool runOnFunction(Function &F) override; private: void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.addPreserved(); AU.addPreserved(); } }; } // namespace bool NewGVNLegacyPass::runOnFunction(Function &F) { if (skipFunction(F)) return false; return NewGVN(F, &getAnalysis().getDomTree(), &getAnalysis().getAssumptionCache(F), &getAnalysis().getTLI(), &getAnalysis().getAAResults(), &getAnalysis().getMSSA(), F.getParent()->getDataLayout()) .runGVN(); } INITIALIZE_PASS_BEGIN(NewGVNLegacyPass, "newgvn", "Global Value Numbering", false, false) INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass) INITIALIZE_PASS_END(NewGVNLegacyPass, "newgvn", "Global Value Numbering", false, false) char NewGVNLegacyPass::ID = 0; // createGVNPass - The public interface to this file. FunctionPass *llvm::createNewGVNPass() { return new NewGVNLegacyPass(); } PreservedAnalyses NewGVNPass::run(Function &F, AnalysisManager &AM) { // Apparently the order in which we get these results matter for // the old GVN (see Chandler's comment in GVN.cpp). I'll keep // the same order here, just in case. auto &AC = AM.getResult(F); auto &DT = AM.getResult(F); auto &TLI = AM.getResult(F); auto &AA = AM.getResult(F); auto &MSSA = AM.getResult(F).getMSSA(); bool Changed = NewGVN(F, &DT, &AC, &TLI, &AA, &MSSA, F.getParent()->getDataLayout()) .runGVN(); if (!Changed) return PreservedAnalyses::all(); PreservedAnalyses PA; PA.preserve(); PA.preserve(); return PA; } Index: head/contrib/llvm/tools/clang/lib/Basic/Version.cpp =================================================================== --- head/contrib/llvm/tools/clang/lib/Basic/Version.cpp (revision 326908) +++ head/contrib/llvm/tools/clang/lib/Basic/Version.cpp (revision 326909) @@ -1,151 +1,151 @@ //===- Version.cpp - Clang Version Number -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines several version-related utility functions for Clang. // //===----------------------------------------------------------------------===// #include "clang/Basic/Version.h" #include "clang/Basic/LLVM.h" #include "clang/Config/config.h" #include "llvm/Support/raw_ostream.h" #include #include #ifdef HAVE_SVN_VERSION_INC # include "SVNVersion.inc" #endif namespace clang { std::string getClangRepositoryPath() { #if defined(CLANG_REPOSITORY_STRING) return CLANG_REPOSITORY_STRING; #else #ifdef SVN_REPOSITORY StringRef URL(SVN_REPOSITORY); #else StringRef URL(""); #endif // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us // pick up a tag in an SVN export, for example. - StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/branches/release_50/lib/Basic/Version.cpp $"); + StringRef SVNRepository("$URL: https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_501/final/lib/Basic/Version.cpp $"); if (URL.empty()) { URL = SVNRepository.slice(SVNRepository.find(':'), SVNRepository.find("/lib/Basic")); } // Strip off version from a build from an integration branch. URL = URL.slice(0, URL.find("/src/tools/clang")); // Trim path prefix off, assuming path came from standard cfe path. size_t Start = URL.find("cfe/"); if (Start != StringRef::npos) URL = URL.substr(Start + 4); return URL; #endif } std::string getLLVMRepositoryPath() { #ifdef LLVM_REPOSITORY StringRef URL(LLVM_REPOSITORY); #else StringRef URL(""); #endif // Trim path prefix off, assuming path came from standard llvm path. // Leave "llvm/" prefix to distinguish the following llvm revision from the // clang revision. size_t Start = URL.find("llvm/"); if (Start != StringRef::npos) URL = URL.substr(Start); return URL; } std::string getClangRevision() { #ifdef SVN_REVISION return SVN_REVISION; #else return ""; #endif } std::string getLLVMRevision() { #ifdef LLVM_REVISION return LLVM_REVISION; #else return ""; #endif } std::string getClangFullRepositoryVersion() { std::string buf; llvm::raw_string_ostream OS(buf); std::string Path = getClangRepositoryPath(); std::string Revision = getClangRevision(); if (!Path.empty() || !Revision.empty()) { OS << '('; if (!Path.empty()) OS << Path; if (!Revision.empty()) { if (!Path.empty()) OS << ' '; OS << Revision; } OS << ')'; } // Support LLVM in a separate repository. std::string LLVMRev = getLLVMRevision(); if (!LLVMRev.empty() && LLVMRev != Revision) { OS << " ("; std::string LLVMRepo = getLLVMRepositoryPath(); if (!LLVMRepo.empty()) OS << LLVMRepo << ' '; OS << LLVMRev << ')'; } return OS.str(); } std::string getClangFullVersion() { return getClangToolFullVersion("clang"); } std::string getClangToolFullVersion(StringRef ToolName) { std::string buf; llvm::raw_string_ostream OS(buf); #ifdef CLANG_VENDOR OS << CLANG_VENDOR; #endif OS << ToolName << " version " CLANG_VERSION_STRING " " << getClangFullRepositoryVersion(); // If vendor supplied, include the base LLVM version as well. #ifdef CLANG_VENDOR OS << " (based on " << BACKEND_PACKAGE_STRING << ")"; #endif return OS.str(); } std::string getClangFullCPPVersion() { // The version string we report in __VERSION__ is just a compacted version of // the one we report on the command line. std::string buf; llvm::raw_string_ostream OS(buf); #ifdef CLANG_VENDOR OS << CLANG_VENDOR; #endif OS << "Clang " CLANG_VERSION_STRING " " << getClangFullRepositoryVersion(); return OS.str(); } } // end namespace clang Index: head/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp =================================================================== --- head/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp (revision 326908) +++ head/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp (revision 326909) @@ -1,16417 +1,16433 @@ //===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements semantic analysis for declarations. // //===----------------------------------------------------------------------===// #include "TypeLocBuilder.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" #include "clang/AST/CommentDiagnostic.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/HeaderSearch.h" // TODO: Sema shouldn't depend on Lex #include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering. #include "clang/Lex/ModuleLoader.h" // TODO: Sema shouldn't depend on Lex #include "clang/Lex/Preprocessor.h" // Included for isCodeCompletionEnabled() #include "clang/Sema/CXXFieldCollector.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Triple.h" #include #include #include using namespace clang; using namespace sema; Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) { if (OwnedType) { Decl *Group[2] = { OwnedType, Ptr }; return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, 2)); } return DeclGroupPtrTy::make(DeclGroupRef(Ptr)); } namespace { class TypeNameValidatorCCC : public CorrectionCandidateCallback { public: TypeNameValidatorCCC(bool AllowInvalid, bool WantClass = false, bool AllowTemplates = false, bool AllowNonTemplates = true) : AllowInvalidDecl(AllowInvalid), WantClassName(WantClass), AllowTemplates(AllowTemplates), AllowNonTemplates(AllowNonTemplates) { WantExpressionKeywords = false; WantCXXNamedCasts = false; WantRemainingKeywords = false; } bool ValidateCandidate(const TypoCorrection &candidate) override { if (NamedDecl *ND = candidate.getCorrectionDecl()) { if (!AllowInvalidDecl && ND->isInvalidDecl()) return false; if (getAsTypeTemplateDecl(ND)) return AllowTemplates; bool IsType = isa(ND) || isa(ND); if (!IsType) return false; if (AllowNonTemplates) return true; // An injected-class-name of a class template (specialization) is valid // as a template or as a non-template. if (AllowTemplates) { auto *RD = dyn_cast(ND); if (!RD || !RD->isInjectedClassName()) return false; RD = cast(RD->getDeclContext()); return RD->getDescribedClassTemplate() || isa(RD); } return false; } return !WantClassName && candidate.isKeyword(); } private: bool AllowInvalidDecl; bool WantClassName; bool AllowTemplates; bool AllowNonTemplates; }; } // end anonymous namespace /// \brief Determine whether the token kind starts a simple-type-specifier. bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const { switch (Kind) { // FIXME: Take into account the current language when deciding whether a // token kind is a valid type specifier case tok::kw_short: case tok::kw_long: case tok::kw___int64: case tok::kw___int128: case tok::kw_signed: case tok::kw_unsigned: case tok::kw_void: case tok::kw_char: case tok::kw_int: case tok::kw_half: case tok::kw_float: case tok::kw_double: case tok::kw___float128: case tok::kw_wchar_t: case tok::kw_bool: case tok::kw___underlying_type: case tok::kw___auto_type: return true; case tok::annot_typename: case tok::kw_char16_t: case tok::kw_char32_t: case tok::kw_typeof: case tok::annot_decltype: case tok::kw_decltype: return getLangOpts().CPlusPlus; default: break; } return false; } namespace { enum class UnqualifiedTypeNameLookupResult { NotFound, FoundNonType, FoundType }; } // end anonymous namespace /// \brief Tries to perform unqualified lookup of the type decls in bases for /// dependent class. /// \return \a NotFound if no any decls is found, \a FoundNotType if found not a /// type decl, \a FoundType if only type decls are found. static UnqualifiedTypeNameLookupResult lookupUnqualifiedTypeNameInBase(Sema &S, const IdentifierInfo &II, SourceLocation NameLoc, const CXXRecordDecl *RD) { if (!RD->hasDefinition()) return UnqualifiedTypeNameLookupResult::NotFound; // Look for type decls in base classes. UnqualifiedTypeNameLookupResult FoundTypeDecl = UnqualifiedTypeNameLookupResult::NotFound; for (const auto &Base : RD->bases()) { const CXXRecordDecl *BaseRD = nullptr; if (auto *BaseTT = Base.getType()->getAs()) BaseRD = BaseTT->getAsCXXRecordDecl(); else if (auto *TST = Base.getType()->getAs()) { // Look for type decls in dependent base classes that have known primary // templates. if (!TST || !TST->isDependentType()) continue; auto *TD = TST->getTemplateName().getAsTemplateDecl(); if (!TD) continue; if (auto *BasePrimaryTemplate = dyn_cast_or_null(TD->getTemplatedDecl())) { if (BasePrimaryTemplate->getCanonicalDecl() != RD->getCanonicalDecl()) BaseRD = BasePrimaryTemplate; else if (auto *CTD = dyn_cast(TD)) { if (const ClassTemplatePartialSpecializationDecl *PS = CTD->findPartialSpecialization(Base.getType())) if (PS->getCanonicalDecl() != RD->getCanonicalDecl()) BaseRD = PS; } } } if (BaseRD) { for (NamedDecl *ND : BaseRD->lookup(&II)) { if (!isa(ND)) return UnqualifiedTypeNameLookupResult::FoundNonType; FoundTypeDecl = UnqualifiedTypeNameLookupResult::FoundType; } if (FoundTypeDecl == UnqualifiedTypeNameLookupResult::NotFound) { switch (lookupUnqualifiedTypeNameInBase(S, II, NameLoc, BaseRD)) { case UnqualifiedTypeNameLookupResult::FoundNonType: return UnqualifiedTypeNameLookupResult::FoundNonType; case UnqualifiedTypeNameLookupResult::FoundType: FoundTypeDecl = UnqualifiedTypeNameLookupResult::FoundType; break; case UnqualifiedTypeNameLookupResult::NotFound: break; } } } } return FoundTypeDecl; } static ParsedType recoverFromTypeInKnownDependentBase(Sema &S, const IdentifierInfo &II, SourceLocation NameLoc) { // Lookup in the parent class template context, if any. const CXXRecordDecl *RD = nullptr; UnqualifiedTypeNameLookupResult FoundTypeDecl = UnqualifiedTypeNameLookupResult::NotFound; for (DeclContext *DC = S.CurContext; DC && FoundTypeDecl == UnqualifiedTypeNameLookupResult::NotFound; DC = DC->getParent()) { // Look for type decls in dependent base classes that have known primary // templates. RD = dyn_cast(DC); if (RD && RD->getDescribedClassTemplate()) FoundTypeDecl = lookupUnqualifiedTypeNameInBase(S, II, NameLoc, RD); } if (FoundTypeDecl != UnqualifiedTypeNameLookupResult::FoundType) return nullptr; // We found some types in dependent base classes. Recover as if the user // wrote 'typename MyClass::II' instead of 'II'. We'll fully resolve the // lookup during template instantiation. S.Diag(NameLoc, diag::ext_found_via_dependent_bases_lookup) << &II; ASTContext &Context = S.Context; auto *NNS = NestedNameSpecifier::Create(Context, nullptr, false, cast(Context.getRecordType(RD))); QualType T = Context.getDependentNameType(ETK_Typename, NNS, &II); CXXScopeSpec SS; SS.MakeTrivial(Context, NNS, SourceRange(NameLoc)); TypeLocBuilder Builder; DependentNameTypeLoc DepTL = Builder.push(T); DepTL.setNameLoc(NameLoc); DepTL.setElaboratedKeywordLoc(SourceLocation()); DepTL.setQualifierLoc(SS.getWithLocInContext(Context)); return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); } /// \brief If the identifier refers to a type name within this scope, /// return the declaration of that type. /// /// This routine performs ordinary name lookup of the identifier II /// within the given scope, with optional C++ scope specifier SS, to /// determine whether the name refers to a type. If so, returns an /// opaque pointer (actually a QualType) corresponding to that /// type. Otherwise, returns NULL. ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS, bool isClassName, bool HasTrailingDot, ParsedType ObjectTypePtr, bool IsCtorOrDtorName, bool WantNontrivialTypeSourceInfo, bool IsClassTemplateDeductionContext, IdentifierInfo **CorrectedII) { // FIXME: Consider allowing this outside C++1z mode as an extension. bool AllowDeducedTemplate = IsClassTemplateDeductionContext && getLangOpts().CPlusPlus1z && !IsCtorOrDtorName && !isClassName && !HasTrailingDot; // Determine where we will perform name lookup. DeclContext *LookupCtx = nullptr; if (ObjectTypePtr) { QualType ObjectType = ObjectTypePtr.get(); if (ObjectType->isRecordType()) LookupCtx = computeDeclContext(ObjectType); } else if (SS && SS->isNotEmpty()) { LookupCtx = computeDeclContext(*SS, false); if (!LookupCtx) { if (isDependentScopeSpecifier(*SS)) { // C++ [temp.res]p3: // A qualified-id that refers to a type and in which the // nested-name-specifier depends on a template-parameter (14.6.2) // shall be prefixed by the keyword typename to indicate that the // qualified-id denotes a type, forming an // elaborated-type-specifier (7.1.5.3). // // We therefore do not perform any name lookup if the result would // refer to a member of an unknown specialization. if (!isClassName && !IsCtorOrDtorName) return nullptr; // We know from the grammar that this name refers to a type, // so build a dependent node to describe the type. if (WantNontrivialTypeSourceInfo) return ActOnTypenameType(S, SourceLocation(), *SS, II, NameLoc).get(); NestedNameSpecifierLoc QualifierLoc = SS->getWithLocInContext(Context); QualType T = CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc, II, NameLoc); return ParsedType::make(T); } return nullptr; } if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(*SS, LookupCtx)) return nullptr; } // FIXME: LookupNestedNameSpecifierName isn't the right kind of // lookup for class-names. LookupNameKind Kind = isClassName ? LookupNestedNameSpecifierName : LookupOrdinaryName; LookupResult Result(*this, &II, NameLoc, Kind); if (LookupCtx) { // Perform "qualified" name lookup into the declaration context we // computed, which is either the type of the base of a member access // expression or the declaration context associated with a prior // nested-name-specifier. LookupQualifiedName(Result, LookupCtx); if (ObjectTypePtr && Result.empty()) { // C++ [basic.lookup.classref]p3: // If the unqualified-id is ~type-name, the type-name is looked up // in the context of the entire postfix-expression. If the type T of // the object expression is of a class type C, the type-name is also // looked up in the scope of class C. At least one of the lookups shall // find a name that refers to (possibly cv-qualified) T. LookupName(Result, S); } } else { // Perform unqualified name lookup. LookupName(Result, S); // For unqualified lookup in a class template in MSVC mode, look into // dependent base classes where the primary class template is known. if (Result.empty() && getLangOpts().MSVCCompat && (!SS || SS->isEmpty())) { if (ParsedType TypeInBase = recoverFromTypeInKnownDependentBase(*this, II, NameLoc)) return TypeInBase; } } NamedDecl *IIDecl = nullptr; switch (Result.getResultKind()) { case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: if (CorrectedII) { TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(), Kind, S, SS, llvm::make_unique( true, isClassName, AllowDeducedTemplate), CTK_ErrorRecovery); IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo(); TemplateTy Template; bool MemberOfUnknownSpecialization; UnqualifiedId TemplateName; TemplateName.setIdentifier(NewII, NameLoc); NestedNameSpecifier *NNS = Correction.getCorrectionSpecifier(); CXXScopeSpec NewSS, *NewSSPtr = SS; if (SS && NNS) { NewSS.MakeTrivial(Context, NNS, SourceRange(NameLoc)); NewSSPtr = &NewSS; } if (Correction && (NNS || NewII != &II) && // Ignore a correction to a template type as the to-be-corrected // identifier is not a template (typo correction for template names // is handled elsewhere). !(getLangOpts().CPlusPlus && NewSSPtr && isTemplateName(S, *NewSSPtr, false, TemplateName, nullptr, false, Template, MemberOfUnknownSpecialization))) { ParsedType Ty = getTypeName(*NewII, NameLoc, S, NewSSPtr, isClassName, HasTrailingDot, ObjectTypePtr, IsCtorOrDtorName, WantNontrivialTypeSourceInfo, IsClassTemplateDeductionContext); if (Ty) { diagnoseTypo(Correction, PDiag(diag::err_unknown_type_or_class_name_suggest) << Result.getLookupName() << isClassName); if (SS && NNS) SS->MakeTrivial(Context, NNS, SourceRange(NameLoc)); *CorrectedII = NewII; return Ty; } } } // If typo correction failed or was not performed, fall through LLVM_FALLTHROUGH; case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: Result.suppressDiagnostics(); return nullptr; case LookupResult::Ambiguous: // Recover from type-hiding ambiguities by hiding the type. We'll // do the lookup again when looking for an object, and we can // diagnose the error then. If we don't do this, then the error // about hiding the type will be immediately followed by an error // that only makes sense if the identifier was treated like a type. if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) { Result.suppressDiagnostics(); return nullptr; } // Look to see if we have a type anywhere in the list of results. for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end(); Res != ResEnd; ++Res) { if (isa(*Res) || isa(*Res) || (AllowDeducedTemplate && getAsTypeTemplateDecl(*Res))) { if (!IIDecl || (*Res)->getLocation().getRawEncoding() < IIDecl->getLocation().getRawEncoding()) IIDecl = *Res; } } if (!IIDecl) { // None of the entities we found is a type, so there is no way // to even assume that the result is a type. In this case, don't // complain about the ambiguity. The parser will either try to // perform this lookup again (e.g., as an object name), which // will produce the ambiguity, or will complain that it expected // a type name. Result.suppressDiagnostics(); return nullptr; } // We found a type within the ambiguous lookup; diagnose the // ambiguity and then return that type. This might be the right // answer, or it might not be, but it suppresses any attempt to // perform the name lookup again. break; case LookupResult::Found: IIDecl = Result.getFoundDecl(); break; } assert(IIDecl && "Didn't find decl"); QualType T; if (TypeDecl *TD = dyn_cast(IIDecl)) { // C++ [class.qual]p2: A lookup that would find the injected-class-name // instead names the constructors of the class, except when naming a class. // This is ill-formed when we're not actually forming a ctor or dtor name. auto *LookupRD = dyn_cast_or_null(LookupCtx); auto *FoundRD = dyn_cast(TD); if (!isClassName && !IsCtorOrDtorName && LookupRD && FoundRD && FoundRD->isInjectedClassName() && declaresSameEntity(LookupRD, cast(FoundRD->getParent()))) Diag(NameLoc, diag::err_out_of_line_qualified_id_type_names_constructor) << &II << /*Type*/1; DiagnoseUseOfDecl(IIDecl, NameLoc); T = Context.getTypeDeclType(TD); MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false); } else if (ObjCInterfaceDecl *IDecl = dyn_cast(IIDecl)) { (void)DiagnoseUseOfDecl(IDecl, NameLoc); if (!HasTrailingDot) T = Context.getObjCInterfaceType(IDecl); } else if (AllowDeducedTemplate) { if (auto *TD = getAsTypeTemplateDecl(IIDecl)) T = Context.getDeducedTemplateSpecializationType(TemplateName(TD), QualType(), false); } if (T.isNull()) { // If it's not plausibly a type, suppress diagnostics. Result.suppressDiagnostics(); return nullptr; } // NOTE: avoid constructing an ElaboratedType(Loc) if this is a // constructor or destructor name (in such a case, the scope specifier // will be attached to the enclosing Expr or Decl node). if (SS && SS->isNotEmpty() && !IsCtorOrDtorName && !isa(IIDecl)) { if (WantNontrivialTypeSourceInfo) { // Construct a type with type-source information. TypeLocBuilder Builder; Builder.pushTypeSpec(T).setNameLoc(NameLoc); T = getElaboratedType(ETK_None, *SS, T); ElaboratedTypeLoc ElabTL = Builder.push(T); ElabTL.setElaboratedKeywordLoc(SourceLocation()); ElabTL.setQualifierLoc(SS->getWithLocInContext(Context)); return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); } else { T = getElaboratedType(ETK_None, *SS, T); } } return ParsedType::make(T); } // Builds a fake NNS for the given decl context. static NestedNameSpecifier * synthesizeCurrentNestedNameSpecifier(ASTContext &Context, DeclContext *DC) { for (;; DC = DC->getLookupParent()) { DC = DC->getPrimaryContext(); auto *ND = dyn_cast(DC); if (ND && !ND->isInline() && !ND->isAnonymousNamespace()) return NestedNameSpecifier::Create(Context, nullptr, ND); else if (auto *RD = dyn_cast(DC)) return NestedNameSpecifier::Create(Context, nullptr, RD->isTemplateDecl(), RD->getTypeForDecl()); else if (isa(DC)) return NestedNameSpecifier::GlobalSpecifier(Context); } llvm_unreachable("something isn't in TU scope?"); } /// Find the parent class with dependent bases of the innermost enclosing method /// context. Do not look for enclosing CXXRecordDecls directly, or we will end /// up allowing unqualified dependent type names at class-level, which MSVC /// correctly rejects. static const CXXRecordDecl * findRecordWithDependentBasesOfEnclosingMethod(const DeclContext *DC) { for (; DC && DC->isDependentContext(); DC = DC->getLookupParent()) { DC = DC->getPrimaryContext(); if (const auto *MD = dyn_cast(DC)) if (MD->getParent()->hasAnyDependentBases()) return MD->getParent(); } return nullptr; } ParsedType Sema::ActOnMSVCUnknownTypeName(const IdentifierInfo &II, SourceLocation NameLoc, bool IsTemplateTypeArg) { assert(getLangOpts().MSVCCompat && "shouldn't be called in non-MSVC mode"); NestedNameSpecifier *NNS = nullptr; if (IsTemplateTypeArg && getCurScope()->isTemplateParamScope()) { // If we weren't able to parse a default template argument, delay lookup // until instantiation time by making a non-dependent DependentTypeName. We // pretend we saw a NestedNameSpecifier referring to the current scope, and // lookup is retried. // FIXME: This hurts our diagnostic quality, since we get errors like "no // type named 'Foo' in 'current_namespace'" when the user didn't write any // name specifiers. NNS = synthesizeCurrentNestedNameSpecifier(Context, CurContext); Diag(NameLoc, diag::ext_ms_delayed_template_argument) << &II; } else if (const CXXRecordDecl *RD = findRecordWithDependentBasesOfEnclosingMethod(CurContext)) { // Build a DependentNameType that will perform lookup into RD at // instantiation time. NNS = NestedNameSpecifier::Create(Context, nullptr, RD->isTemplateDecl(), RD->getTypeForDecl()); // Diagnose that this identifier was undeclared, and retry the lookup during // template instantiation. Diag(NameLoc, diag::ext_undeclared_unqual_id_with_dependent_base) << &II << RD; } else { // This is not a situation that we should recover from. return ParsedType(); } QualType T = Context.getDependentNameType(ETK_None, NNS, &II); // Build type location information. We synthesized the qualifier, so we have // to build a fake NestedNameSpecifierLoc. NestedNameSpecifierLocBuilder NNSLocBuilder; NNSLocBuilder.MakeTrivial(Context, NNS, SourceRange(NameLoc)); NestedNameSpecifierLoc QualifierLoc = NNSLocBuilder.getWithLocInContext(Context); TypeLocBuilder Builder; DependentNameTypeLoc DepTL = Builder.push(T); DepTL.setNameLoc(NameLoc); DepTL.setElaboratedKeywordLoc(SourceLocation()); DepTL.setQualifierLoc(QualifierLoc); return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); } /// isTagName() - This method is called *for error recovery purposes only* /// to determine if the specified name is a valid tag name ("struct foo"). If /// so, this returns the TST for the tag corresponding to it (TST_enum, /// TST_union, TST_struct, TST_interface, TST_class). This is used to diagnose /// cases in C where the user forgot to specify the tag. DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { // Do a tag name lookup in this scope. LookupResult R(*this, &II, SourceLocation(), LookupTagName); LookupName(R, S, false); R.suppressDiagnostics(); if (R.getResultKind() == LookupResult::Found) if (const TagDecl *TD = R.getAsSingle()) { switch (TD->getTagKind()) { case TTK_Struct: return DeclSpec::TST_struct; case TTK_Interface: return DeclSpec::TST_interface; case TTK_Union: return DeclSpec::TST_union; case TTK_Class: return DeclSpec::TST_class; case TTK_Enum: return DeclSpec::TST_enum; } } return DeclSpec::TST_unspecified; } /// isMicrosoftMissingTypename - In Microsoft mode, within class scope, /// if a CXXScopeSpec's type is equal to the type of one of the base classes /// then downgrade the missing typename error to a warning. /// This is needed for MSVC compatibility; Example: /// @code /// template class A { /// public: /// typedef int TYPE; /// }; /// template class B : public A { /// public: /// A::TYPE a; // no typename required because A is a base class. /// }; /// @endcode bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) { if (CurContext->isRecord()) { if (SS->getScopeRep()->getKind() == NestedNameSpecifier::Super) return true; const Type *Ty = SS->getScopeRep()->getAsType(); CXXRecordDecl *RD = cast(CurContext); for (const auto &Base : RD->bases()) if (Ty && Context.hasSameUnqualifiedType(QualType(Ty, 1), Base.getType())) return true; return S->isFunctionPrototypeScope(); } return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope(); } void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, SourceLocation IILoc, Scope *S, CXXScopeSpec *SS, ParsedType &SuggestedType, bool IsTemplateName) { // Don't report typename errors for editor placeholders. if (II->isEditorPlaceholder()) return; // We don't have anything to suggest (yet). SuggestedType = nullptr; // There may have been a typo in the name of the type. Look up typo // results, in case we have something that we can suggest. if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(II, IILoc), LookupOrdinaryName, S, SS, llvm::make_unique( false, false, IsTemplateName, !IsTemplateName), CTK_ErrorRecovery)) { // FIXME: Support error recovery for the template-name case. bool CanRecover = !IsTemplateName; if (Corrected.isKeyword()) { // We corrected to a keyword. diagnoseTypo(Corrected, PDiag(IsTemplateName ? diag::err_no_template_suggest : diag::err_unknown_typename_suggest) << II); II = Corrected.getCorrectionAsIdentifierInfo(); } else { // We found a similarly-named type or interface; suggest that. if (!SS || !SS->isSet()) { diagnoseTypo(Corrected, PDiag(IsTemplateName ? diag::err_no_template_suggest : diag::err_unknown_typename_suggest) << II, CanRecover); } else if (DeclContext *DC = computeDeclContext(*SS, false)) { std::string CorrectedStr(Corrected.getAsString(getLangOpts())); bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && II->getName().equals(CorrectedStr); diagnoseTypo(Corrected, PDiag(IsTemplateName ? diag::err_no_member_template_suggest : diag::err_unknown_nested_typename_suggest) << II << DC << DroppedSpecifier << SS->getRange(), CanRecover); } else { llvm_unreachable("could not have corrected a typo here"); } if (!CanRecover) return; CXXScopeSpec tmpSS; if (Corrected.getCorrectionSpecifier()) tmpSS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(), SourceRange(IILoc)); // FIXME: Support class template argument deduction here. SuggestedType = getTypeName(*Corrected.getCorrectionAsIdentifierInfo(), IILoc, S, tmpSS.isSet() ? &tmpSS : SS, false, false, nullptr, /*IsCtorOrDtorName=*/false, /*NonTrivialTypeSourceInfo=*/true); } return; } if (getLangOpts().CPlusPlus && !IsTemplateName) { // See if II is a class template that the user forgot to pass arguments to. UnqualifiedId Name; Name.setIdentifier(II, IILoc); CXXScopeSpec EmptySS; TemplateTy TemplateResult; bool MemberOfUnknownSpecialization; if (isTemplateName(S, SS ? *SS : EmptySS, /*hasTemplateKeyword=*/false, Name, nullptr, true, TemplateResult, MemberOfUnknownSpecialization) == TNK_Type_template) { TemplateName TplName = TemplateResult.get(); Diag(IILoc, diag::err_template_missing_args) << (int)getTemplateNameKindForDiagnostics(TplName) << TplName; if (TemplateDecl *TplDecl = TplName.getAsTemplateDecl()) { Diag(TplDecl->getLocation(), diag::note_template_decl_here) << TplDecl->getTemplateParameters()->getSourceRange(); } return; } } // FIXME: Should we move the logic that tries to recover from a missing tag // (struct, union, enum) from Parser::ParseImplicitInt here, instead? if (!SS || (!SS->isSet() && !SS->isInvalid())) Diag(IILoc, IsTemplateName ? diag::err_no_template : diag::err_unknown_typename) << II; else if (DeclContext *DC = computeDeclContext(*SS, false)) Diag(IILoc, IsTemplateName ? diag::err_no_member_template : diag::err_typename_nested_not_found) << II << DC << SS->getRange(); else if (isDependentScopeSpecifier(*SS)) { unsigned DiagID = diag::err_typename_missing; if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S)) DiagID = diag::ext_typename_missing; Diag(SS->getRange().getBegin(), DiagID) << SS->getScopeRep() << II->getName() << SourceRange(SS->getRange().getBegin(), IILoc) << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename "); SuggestedType = ActOnTypenameType(S, SourceLocation(), *SS, *II, IILoc).get(); } else { assert(SS && SS->isInvalid() && "Invalid scope specifier has already been diagnosed"); } } /// \brief Determine whether the given result set contains either a type name /// or static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) { bool CheckTemplate = R.getSema().getLangOpts().CPlusPlus && NextToken.is(tok::less); for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) { if (isa(*I) || isa(*I)) return true; if (CheckTemplate && isa(*I)) return true; } return false; } static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result, Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name, SourceLocation NameLoc) { LookupResult R(SemaRef, Name, NameLoc, Sema::LookupTagName); SemaRef.LookupParsedName(R, S, &SS); if (TagDecl *Tag = R.getAsSingle()) { StringRef FixItTagName; switch (Tag->getTagKind()) { case TTK_Class: FixItTagName = "class "; break; case TTK_Enum: FixItTagName = "enum "; break; case TTK_Struct: FixItTagName = "struct "; break; case TTK_Interface: FixItTagName = "__interface "; break; case TTK_Union: FixItTagName = "union "; break; } StringRef TagName = FixItTagName.drop_back(); SemaRef.Diag(NameLoc, diag::err_use_of_tag_name_without_tag) << Name << TagName << SemaRef.getLangOpts().CPlusPlus << FixItHint::CreateInsertion(NameLoc, FixItTagName); for (LookupResult::iterator I = Result.begin(), IEnd = Result.end(); I != IEnd; ++I) SemaRef.Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type) << Name << TagName; // Replace lookup results with just the tag decl. Result.clear(Sema::LookupTagName); SemaRef.LookupParsedName(Result, S, &SS); return true; } return false; } /// Build a ParsedType for a simple-type-specifier with a nested-name-specifier. static ParsedType buildNestedType(Sema &S, CXXScopeSpec &SS, QualType T, SourceLocation NameLoc) { ASTContext &Context = S.Context; TypeLocBuilder Builder; Builder.pushTypeSpec(T).setNameLoc(NameLoc); T = S.getElaboratedType(ETK_None, SS, T); ElaboratedTypeLoc ElabTL = Builder.push(T); ElabTL.setElaboratedKeywordLoc(SourceLocation()); ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); } Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name, SourceLocation NameLoc, const Token &NextToken, bool IsAddressOfOperand, std::unique_ptr CCC) { DeclarationNameInfo NameInfo(Name, NameLoc); ObjCMethodDecl *CurMethod = getCurMethodDecl(); if (NextToken.is(tok::coloncolon)) { NestedNameSpecInfo IdInfo(Name, NameLoc, NextToken.getLocation()); BuildCXXNestedNameSpecifier(S, IdInfo, false, SS, nullptr, false); } else if (getLangOpts().CPlusPlus && SS.isSet() && isCurrentClassName(*Name, S, &SS)) { // Per [class.qual]p2, this names the constructors of SS, not the // injected-class-name. We don't have a classification for that. // There's not much point caching this result, since the parser // will reject it later. return NameClassification::Unknown(); } LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); LookupParsedName(Result, S, &SS, !CurMethod); // For unqualified lookup in a class template in MSVC mode, look into // dependent base classes where the primary class template is known. if (Result.empty() && SS.isEmpty() && getLangOpts().MSVCCompat) { if (ParsedType TypeInBase = recoverFromTypeInKnownDependentBase(*this, *Name, NameLoc)) return TypeInBase; } // Perform lookup for Objective-C instance variables (including automatically // synthesized instance variables), if we're in an Objective-C method. // FIXME: This lookup really, really needs to be folded in to the normal // unqualified lookup mechanism. if (!SS.isSet() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) { ExprResult E = LookupInObjCMethod(Result, S, Name, true); if (E.get() || E.isInvalid()) return E; } bool SecondTry = false; bool IsFilteredTemplateName = false; Corrected: switch (Result.getResultKind()) { case LookupResult::NotFound: // If an unqualified-id is followed by a '(', then we have a function // call. if (!SS.isSet() && NextToken.is(tok::l_paren)) { // In C++, this is an ADL-only call. // FIXME: Reference? if (getLangOpts().CPlusPlus) return BuildDeclarationNameExpr(SS, Result, /*ADL=*/true); // C90 6.3.2.2: // If the expression that precedes the parenthesized argument list in a // function call consists solely of an identifier, and if no // declaration is visible for this identifier, the identifier is // implicitly declared exactly as if, in the innermost block containing // the function call, the declaration // // extern int identifier (); // // appeared. // // We also allow this in C99 as an extension. if (NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *Name, S)) { Result.addDecl(D); Result.resolveKind(); return BuildDeclarationNameExpr(SS, Result, /*ADL=*/false); } } // In C, we first see whether there is a tag type by the same name, in // which case it's likely that the user just forgot to write "enum", // "struct", or "union". if (!getLangOpts().CPlusPlus && !SecondTry && isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) { break; } // Perform typo correction to determine if there is another name that is // close to this name. if (!SecondTry && CCC) { SecondTry = true; if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(), Result.getLookupKind(), S, &SS, std::move(CCC), CTK_ErrorRecovery)) { unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; unsigned QualifiedDiag = diag::err_no_member_suggest; NamedDecl *FirstDecl = Corrected.getFoundDecl(); NamedDecl *UnderlyingFirstDecl = Corrected.getCorrectionDecl(); if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && UnderlyingFirstDecl && isa(UnderlyingFirstDecl)) { UnqualifiedDiag = diag::err_no_template_suggest; QualifiedDiag = diag::err_no_member_template_suggest; } else if (UnderlyingFirstDecl && (isa(UnderlyingFirstDecl) || isa(UnderlyingFirstDecl) || isa(UnderlyingFirstDecl))) { UnqualifiedDiag = diag::err_unknown_typename_suggest; QualifiedDiag = diag::err_unknown_nested_typename_suggest; } if (SS.isEmpty()) { diagnoseTypo(Corrected, PDiag(UnqualifiedDiag) << Name); } else {// FIXME: is this even reachable? Test it. std::string CorrectedStr(Corrected.getAsString(getLangOpts())); bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && Name->getName().equals(CorrectedStr); diagnoseTypo(Corrected, PDiag(QualifiedDiag) << Name << computeDeclContext(SS, false) << DroppedSpecifier << SS.getRange()); } // Update the name, so that the caller has the new name. Name = Corrected.getCorrectionAsIdentifierInfo(); // Typo correction corrected to a keyword. if (Corrected.isKeyword()) return Name; // Also update the LookupResult... // FIXME: This should probably go away at some point Result.clear(); Result.setLookupName(Corrected.getCorrection()); if (FirstDecl) Result.addDecl(FirstDecl); // If we found an Objective-C instance variable, let // LookupInObjCMethod build the appropriate expression to // reference the ivar. // FIXME: This is a gross hack. if (ObjCIvarDecl *Ivar = Result.getAsSingle()) { Result.clear(); ExprResult E(LookupInObjCMethod(Result, S, Ivar->getIdentifier())); return E; } goto Corrected; } } // We failed to correct; just fall through and let the parser deal with it. Result.suppressDiagnostics(); return NameClassification::Unknown(); case LookupResult::NotFoundInCurrentInstantiation: { // We performed name lookup into the current instantiation, and there were // dependent bases, so we treat this result the same way as any other // dependent nested-name-specifier. // C++ [temp.res]p2: // A name used in a template declaration or definition and that is // dependent on a template-parameter is assumed not to name a type // unless the applicable name lookup finds a type name or the name is // qualified by the keyword typename. // // FIXME: If the next token is '<', we might want to ask the parser to // perform some heroics to see if we actually have a // template-argument-list, which would indicate a missing 'template' // keyword here. return ActOnDependentIdExpression(SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo, IsAddressOfOperand, /*TemplateArgs=*/nullptr); } case LookupResult::Found: case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: break; case LookupResult::Ambiguous: if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && hasAnyAcceptableTemplateNames(Result)) { // C++ [temp.local]p3: // A lookup that finds an injected-class-name (10.2) can result in an // ambiguity in certain cases (for example, if it is found in more than // one base class). If all of the injected-class-names that are found // refer to specializations of the same class template, and if the name // is followed by a template-argument-list, the reference refers to the // class template itself and not a specialization thereof, and is not // ambiguous. // // This filtering can make an ambiguous result into an unambiguous one, // so try again after filtering out template names. FilterAcceptableTemplateNames(Result); if (!Result.isAmbiguous()) { IsFilteredTemplateName = true; break; } } // Diagnose the ambiguity and return an error. return NameClassification::Error(); } if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && (IsFilteredTemplateName || hasAnyAcceptableTemplateNames(Result))) { // C++ [temp.names]p3: // After name lookup (3.4) finds that a name is a template-name or that // an operator-function-id or a literal- operator-id refers to a set of // overloaded functions any member of which is a function template if // this is followed by a <, the < is always taken as the delimiter of a // template-argument-list and never as the less-than operator. if (!IsFilteredTemplateName) FilterAcceptableTemplateNames(Result); if (!Result.empty()) { bool IsFunctionTemplate; bool IsVarTemplate; TemplateName Template; if (Result.end() - Result.begin() > 1) { IsFunctionTemplate = true; Template = Context.getOverloadedTemplateName(Result.begin(), Result.end()); } else { TemplateDecl *TD = cast((*Result.begin())->getUnderlyingDecl()); IsFunctionTemplate = isa(TD); IsVarTemplate = isa(TD); if (SS.isSet() && !SS.isInvalid()) Template = Context.getQualifiedTemplateName(SS.getScopeRep(), /*TemplateKeyword=*/false, TD); else Template = TemplateName(TD); } if (IsFunctionTemplate) { // Function templates always go through overload resolution, at which // point we'll perform the various checks (e.g., accessibility) we need // to based on which function we selected. Result.suppressDiagnostics(); return NameClassification::FunctionTemplate(Template); } return IsVarTemplate ? NameClassification::VarTemplate(Template) : NameClassification::TypeTemplate(Template); } } NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl(); if (TypeDecl *Type = dyn_cast(FirstDecl)) { DiagnoseUseOfDecl(Type, NameLoc); MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false); QualType T = Context.getTypeDeclType(Type); if (SS.isNotEmpty()) return buildNestedType(*this, SS, T, NameLoc); return ParsedType::make(T); } ObjCInterfaceDecl *Class = dyn_cast(FirstDecl); if (!Class) { // FIXME: It's unfortunate that we don't have a Type node for handling this. if (ObjCCompatibleAliasDecl *Alias = dyn_cast(FirstDecl)) Class = Alias->getClassInterface(); } if (Class) { DiagnoseUseOfDecl(Class, NameLoc); if (NextToken.is(tok::period)) { // Interface. is parsed as a property reference expression. // Just return "unknown" as a fall-through for now. Result.suppressDiagnostics(); return NameClassification::Unknown(); } QualType T = Context.getObjCInterfaceType(Class); return ParsedType::make(T); } // We can have a type template here if we're classifying a template argument. if (isa(FirstDecl) && !isa(FirstDecl) && !isa(FirstDecl)) return NameClassification::TypeTemplate( TemplateName(cast(FirstDecl))); // Check for a tag type hidden by a non-type decl in a few cases where it // seems likely a type is wanted instead of the non-type that was found. bool NextIsOp = NextToken.isOneOf(tok::amp, tok::star); if ((NextToken.is(tok::identifier) || (NextIsOp && FirstDecl->getUnderlyingDecl()->isFunctionOrFunctionTemplate())) && isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) { TypeDecl *Type = Result.getAsSingle(); DiagnoseUseOfDecl(Type, NameLoc); QualType T = Context.getTypeDeclType(Type); if (SS.isNotEmpty()) return buildNestedType(*this, SS, T, NameLoc); return ParsedType::make(T); } if (FirstDecl->isCXXClassMember()) return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, nullptr, S); bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren)); return BuildDeclarationNameExpr(SS, Result, ADL); } Sema::TemplateNameKindForDiagnostics Sema::getTemplateNameKindForDiagnostics(TemplateName Name) { auto *TD = Name.getAsTemplateDecl(); if (!TD) return TemplateNameKindForDiagnostics::DependentTemplate; if (isa(TD)) return TemplateNameKindForDiagnostics::ClassTemplate; if (isa(TD)) return TemplateNameKindForDiagnostics::FunctionTemplate; if (isa(TD)) return TemplateNameKindForDiagnostics::VarTemplate; if (isa(TD)) return TemplateNameKindForDiagnostics::AliasTemplate; if (isa(TD)) return TemplateNameKindForDiagnostics::TemplateTemplateParam; return TemplateNameKindForDiagnostics::DependentTemplate; } // Determines the context to return to after temporarily entering a // context. This depends in an unnecessarily complicated way on the // exact ordering of callbacks from the parser. DeclContext *Sema::getContainingDC(DeclContext *DC) { // Functions defined inline within classes aren't parsed until we've // finished parsing the top-level class, so the top-level class is // the context we'll need to return to. // A Lambda call operator whose parent is a class must not be treated // as an inline member function. A Lambda can be used legally // either as an in-class member initializer or a default argument. These // are parsed once the class has been marked complete and so the containing // context would be the nested class (when the lambda is defined in one); // If the class is not complete, then the lambda is being used in an // ill-formed fashion (such as to specify the width of a bit-field, or // in an array-bound) - in which case we still want to return the // lexically containing DC (which could be a nested class). if (isa(DC) && !isLambdaCallOperator(DC)) { DC = DC->getLexicalParent(); // A function not defined within a class will always return to its // lexical context. if (!isa(DC)) return DC; // A C++ inline method/friend is parsed *after* the topmost class // it was declared in is fully parsed ("complete"); the topmost // class is the context we need to return to. while (CXXRecordDecl *RD = dyn_cast(DC->getLexicalParent())) DC = RD; // Return the declaration context of the topmost class the inline method is // declared in. return DC; } return DC->getLexicalParent(); } void Sema::PushDeclContext(Scope *S, DeclContext *DC) { assert(getContainingDC(DC) == CurContext && "The next DeclContext should be lexically contained in the current one."); CurContext = DC; S->setEntity(DC); } void Sema::PopDeclContext() { assert(CurContext && "DeclContext imbalance!"); CurContext = getContainingDC(CurContext); assert(CurContext && "Popped translation unit!"); } Sema::SkippedDefinitionContext Sema::ActOnTagStartSkippedDefinition(Scope *S, Decl *D) { // Unlike PushDeclContext, the context to which we return is not necessarily // the containing DC of TD, because the new context will be some pre-existing // TagDecl definition instead of a fresh one. auto Result = static_cast(CurContext); CurContext = cast(D)->getDefinition(); assert(CurContext && "skipping definition of undefined tag"); // Start lookups from the parent of the current context; we don't want to look // into the pre-existing complete definition. S->setEntity(CurContext->getLookupParent()); return Result; } void Sema::ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context) { CurContext = static_cast(Context); } /// EnterDeclaratorContext - Used when we must lookup names in the context /// of a declarator's nested name specifier. /// void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) { // C++0x [basic.lookup.unqual]p13: // A name used in the definition of a static data member of class // X (after the qualified-id of the static member) is looked up as // if the name was used in a member function of X. // C++0x [basic.lookup.unqual]p14: // If a variable member of a namespace is defined outside of the // scope of its namespace then any name used in the definition of // the variable member (after the declarator-id) is looked up as // if the definition of the variable member occurred in its // namespace. // Both of these imply that we should push a scope whose context // is the semantic context of the declaration. We can't use // PushDeclContext here because that context is not necessarily // lexically contained in the current context. Fortunately, // the containing scope should have the appropriate information. assert(!S->getEntity() && "scope already has entity"); #ifndef NDEBUG Scope *Ancestor = S->getParent(); while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent(); assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch"); #endif CurContext = DC; S->setEntity(DC); } void Sema::ExitDeclaratorContext(Scope *S) { assert(S->getEntity() == CurContext && "Context imbalance!"); // Switch back to the lexical context. The safety of this is // enforced by an assert in EnterDeclaratorContext. Scope *Ancestor = S->getParent(); while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent(); CurContext = Ancestor->getEntity(); // We don't need to do anything with the scope, which is going to // disappear. } void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) { // We assume that the caller has already called // ActOnReenterTemplateScope so getTemplatedDecl() works. FunctionDecl *FD = D->getAsFunction(); if (!FD) return; // Same implementation as PushDeclContext, but enters the context // from the lexical parent, rather than the top-level class. assert(CurContext == FD->getLexicalParent() && "The next DeclContext should be lexically contained in the current one."); CurContext = FD; S->setEntity(CurContext); for (unsigned P = 0, NumParams = FD->getNumParams(); P < NumParams; ++P) { ParmVarDecl *Param = FD->getParamDecl(P); // If the parameter has an identifier, then add it to the scope if (Param->getIdentifier()) { S->AddDecl(Param); IdResolver.AddDecl(Param); } } } void Sema::ActOnExitFunctionContext() { // Same implementation as PopDeclContext, but returns to the lexical parent, // rather than the top-level class. assert(CurContext && "DeclContext imbalance!"); CurContext = CurContext->getLexicalParent(); assert(CurContext && "Popped translation unit!"); } /// \brief Determine whether we allow overloading of the function /// PrevDecl with another declaration. /// /// This routine determines whether overloading is possible, not /// whether some new function is actually an overload. It will return /// true in C++ (where we can always provide overloads) or, as an /// extension, in C when the previous function is already an /// overloaded function declaration or has the "overloadable" /// attribute. static bool AllowOverloadingOfFunction(LookupResult &Previous, ASTContext &Context, const FunctionDecl *New) { if (Context.getLangOpts().CPlusPlus) return true; if (Previous.getResultKind() == LookupResult::FoundOverloaded) return true; return Previous.getResultKind() == LookupResult::Found && (Previous.getFoundDecl()->hasAttr() || New->hasAttr()); } /// Add this decl to the scope shadowed decl chains. void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { // Move up the scope chain until we find the nearest enclosing // non-transparent context. The declaration will be introduced into this // scope. while (S->getEntity() && S->getEntity()->isTransparentContext()) S = S->getParent(); // Add scoped declarations into their context, so that they can be // found later. Declarations without a context won't be inserted // into any context. if (AddToContext) CurContext->addDecl(D); // Out-of-line definitions shouldn't be pushed into scope in C++, unless they // are function-local declarations. if (getLangOpts().CPlusPlus && D->isOutOfLine() && !D->getDeclContext()->getRedeclContext()->Equals( D->getLexicalDeclContext()->getRedeclContext()) && !D->getLexicalDeclContext()->isFunctionOrMethod()) return; // Template instantiations should also not be pushed into scope. if (isa(D) && cast(D)->isFunctionTemplateSpecialization()) return; // If this replaces anything in the current scope, IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()), IEnd = IdResolver.end(); for (; I != IEnd; ++I) { if (S->isDeclScope(*I) && D->declarationReplaces(*I)) { S->RemoveDecl(*I); IdResolver.RemoveDecl(*I); // Should only need to replace one decl. break; } } S->AddDecl(D); if (isa(D) && !cast(D)->isGnuLocal()) { // Implicitly-generated labels may end up getting generated in an order that // isn't strictly lexical, which breaks name lookup. Be careful to insert // the label at the appropriate place in the identifier chain. for (I = IdResolver.begin(D->getDeclName()); I != IEnd; ++I) { DeclContext *IDC = (*I)->getLexicalDeclContext()->getRedeclContext(); if (IDC == CurContext) { if (!S->isDeclScope(*I)) continue; } else if (IDC->Encloses(CurContext)) break; } IdResolver.InsertDeclAfter(I, D); } else { IdResolver.AddDecl(D); } } void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { if (IdResolver.tryAddTopLevelDecl(D, Name) && TUScope) TUScope->AddDecl(D); } bool Sema::isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S, bool AllowInlineNamespace) { return IdResolver.isDeclInScope(D, Ctx, S, AllowInlineNamespace); } Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) { DeclContext *TargetDC = DC->getPrimaryContext(); do { if (DeclContext *ScopeDC = S->getEntity()) if (ScopeDC->getPrimaryContext() == TargetDC) return S; } while ((S = S->getParent())); return nullptr; } static bool isOutOfScopePreviousDeclaration(NamedDecl *, DeclContext*, ASTContext&); /// Filters out lookup results that don't fall within the given scope /// as determined by isDeclInScope. void Sema::FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, bool ConsiderLinkage, bool AllowInlineNamespace) { LookupResult::Filter F = R.makeFilter(); while (F.hasNext()) { NamedDecl *D = F.next(); if (isDeclInScope(D, Ctx, S, AllowInlineNamespace)) continue; if (ConsiderLinkage && isOutOfScopePreviousDeclaration(D, Ctx, Context)) continue; F.erase(); } F.done(); } static bool isUsingDecl(NamedDecl *D) { return isa(D) || isa(D) || isa(D); } /// Removes using shadow declarations from the lookup results. static void RemoveUsingDecls(LookupResult &R) { LookupResult::Filter F = R.makeFilter(); while (F.hasNext()) if (isUsingDecl(F.next())) F.erase(); F.done(); } /// \brief Check for this common pattern: /// @code /// class S { /// S(const S&); // DO NOT IMPLEMENT /// void operator=(const S&); // DO NOT IMPLEMENT /// }; /// @endcode static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) { // FIXME: Should check for private access too but access is set after we get // the decl here. if (D->doesThisDeclarationHaveABody()) return false; if (const CXXConstructorDecl *CD = dyn_cast(D)) return CD->isCopyConstructor(); if (const CXXMethodDecl *Method = dyn_cast(D)) return Method->isCopyAssignmentOperator(); return false; } // We need this to handle // // typedef struct { // void *foo() { return 0; } // } A; // // When we see foo we don't know if after the typedef we will get 'A' or '*A' // for example. If 'A', foo will have external linkage. If we have '*A', // foo will have no linkage. Since we can't know until we get to the end // of the typedef, this function finds out if D might have non-external linkage. // Callers should verify at the end of the TU if it D has external linkage or // not. bool Sema::mightHaveNonExternalLinkage(const DeclaratorDecl *D) { const DeclContext *DC = D->getDeclContext(); while (!DC->isTranslationUnit()) { if (const RecordDecl *RD = dyn_cast(DC)){ if (!RD->hasNameForLinkage()) return true; } DC = DC->getParent(); } return !D->isExternallyVisible(); } // FIXME: This needs to be refactored; some other isInMainFile users want // these semantics. static bool isMainFileLoc(const Sema &S, SourceLocation Loc) { if (S.TUKind != TU_Complete) return false; return S.SourceMgr.isInMainFile(Loc); } bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const { assert(D); if (D->isInvalidDecl() || D->isUsed() || D->hasAttr()) return false; // Ignore all entities declared within templates, and out-of-line definitions // of members of class templates. if (D->getDeclContext()->isDependentContext() || D->getLexicalDeclContext()->isDependentContext()) return false; if (const FunctionDecl *FD = dyn_cast(D)) { if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) return false; // A non-out-of-line declaration of a member specialization was implicitly // instantiated; it's the out-of-line declaration that we're interested in. if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization && FD->getMemberSpecializationInfo() && !FD->isOutOfLine()) return false; if (const CXXMethodDecl *MD = dyn_cast(FD)) { if (MD->isVirtual() || IsDisallowedCopyOrAssign(MD)) return false; } else { // 'static inline' functions are defined in headers; don't warn. if (FD->isInlined() && !isMainFileLoc(*this, FD->getLocation())) return false; } if (FD->doesThisDeclarationHaveABody() && Context.DeclMustBeEmitted(FD)) return false; } else if (const VarDecl *VD = dyn_cast(D)) { // Constants and utility variables are defined in headers with internal // linkage; don't warn. (Unlike functions, there isn't a convenient marker // like "inline".) if (!isMainFileLoc(*this, VD->getLocation())) return false; if (Context.DeclMustBeEmitted(VD)) return false; if (VD->isStaticDataMember() && VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) return false; if (VD->isStaticDataMember() && VD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization && VD->getMemberSpecializationInfo() && !VD->isOutOfLine()) return false; if (VD->isInline() && !isMainFileLoc(*this, VD->getLocation())) return false; } else { return false; } // Only warn for unused decls internal to the translation unit. // FIXME: This seems like a bogus check; it suppresses -Wunused-function // for inline functions defined in the main source file, for instance. return mightHaveNonExternalLinkage(D); } void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) { if (!D) return; if (const FunctionDecl *FD = dyn_cast(D)) { const FunctionDecl *First = FD->getFirstDecl(); if (FD != First && ShouldWarnIfUnusedFileScopedDecl(First)) return; // First should already be in the vector. } if (const VarDecl *VD = dyn_cast(D)) { const VarDecl *First = VD->getFirstDecl(); if (VD != First && ShouldWarnIfUnusedFileScopedDecl(First)) return; // First should already be in the vector. } if (ShouldWarnIfUnusedFileScopedDecl(D)) UnusedFileScopedDecls.push_back(D); } static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { if (D->isInvalidDecl()) return false; - if (D->isReferenced() || D->isUsed() || D->hasAttr() || + bool Referenced = false; + if (auto *DD = dyn_cast(D)) { + // For a decomposition declaration, warn if none of the bindings are + // referenced, instead of if the variable itself is referenced (which + // it is, by the bindings' expressions). + for (auto *BD : DD->bindings()) { + if (BD->isReferenced()) { + Referenced = true; + break; + } + } + } else if (!D->getDeclName()) { + return false; + } else if (D->isReferenced() || D->isUsed()) { + Referenced = true; + } + + if (Referenced || D->hasAttr() || D->hasAttr()) return false; if (isa(D)) return true; // Except for labels, we only care about unused decls that are local to // functions. bool WithinFunction = D->getDeclContext()->isFunctionOrMethod(); if (const auto *R = dyn_cast(D->getDeclContext())) // For dependent types, the diagnostic is deferred. WithinFunction = WithinFunction || (R->isLocalClass() && !R->isDependentType()); if (!WithinFunction) return false; if (isa(D)) return true; // White-list anything that isn't a local variable. if (!isa(D) || isa(D) || isa(D)) return false; // Types of valid local variables should be complete, so this should succeed. if (const VarDecl *VD = dyn_cast(D)) { // White-list anything with an __attribute__((unused)) type. const auto *Ty = VD->getType().getTypePtr(); // Only look at the outermost level of typedef. if (const TypedefType *TT = Ty->getAs()) { if (TT->getDecl()->hasAttr()) return false; } // If we failed to complete the type for some reason, or if the type is // dependent, don't diagnose the variable. if (Ty->isIncompleteType() || Ty->isDependentType()) return false; // Look at the element type to ensure that the warning behaviour is // consistent for both scalars and arrays. Ty = Ty->getBaseElementTypeUnsafe(); if (const TagType *TT = Ty->getAs()) { const TagDecl *Tag = TT->getDecl(); if (Tag->hasAttr()) return false; if (const CXXRecordDecl *RD = dyn_cast(Tag)) { if (!RD->hasTrivialDestructor() && !RD->hasAttr()) return false; if (const Expr *Init = VD->getInit()) { if (const ExprWithCleanups *Cleanups = dyn_cast(Init)) Init = Cleanups->getSubExpr(); const CXXConstructExpr *Construct = dyn_cast(Init); if (Construct && !Construct->isElidable()) { CXXConstructorDecl *CD = Construct->getConstructor(); if (!CD->isTrivial() && !RD->hasAttr()) return false; } } } } // TODO: __attribute__((unused)) templates? } return true; } static void GenerateFixForUnusedDecl(const NamedDecl *D, ASTContext &Ctx, FixItHint &Hint) { if (isa(D)) { SourceLocation AfterColon = Lexer::findLocationAfterToken(D->getLocEnd(), tok::colon, Ctx.getSourceManager(), Ctx.getLangOpts(), true); if (AfterColon.isInvalid()) return; Hint = FixItHint::CreateRemoval(CharSourceRange:: getCharRange(D->getLocStart(), AfterColon)); } } void Sema::DiagnoseUnusedNestedTypedefs(const RecordDecl *D) { if (D->getTypeForDecl()->isDependentType()) return; for (auto *TmpD : D->decls()) { if (const auto *T = dyn_cast(TmpD)) DiagnoseUnusedDecl(T); else if(const auto *R = dyn_cast(TmpD)) DiagnoseUnusedNestedTypedefs(R); } } /// DiagnoseUnusedDecl - Emit warnings about declarations that are not used /// unless they are marked attr(unused). void Sema::DiagnoseUnusedDecl(const NamedDecl *D) { if (!ShouldDiagnoseUnusedDecl(D)) return; if (auto *TD = dyn_cast(D)) { // typedefs can be referenced later on, so the diagnostics are emitted // at end-of-translation-unit. UnusedLocalTypedefNameCandidates.insert(TD); return; } FixItHint Hint; GenerateFixForUnusedDecl(D, Context, Hint); unsigned DiagID; if (isa(D) && cast(D)->isExceptionVariable()) DiagID = diag::warn_unused_exception_param; else if (isa(D)) DiagID = diag::warn_unused_label; else DiagID = diag::warn_unused_variable; - Diag(D->getLocation(), DiagID) << D->getDeclName() << Hint; + Diag(D->getLocation(), DiagID) << D << Hint; } static void CheckPoppedLabel(LabelDecl *L, Sema &S) { // Verify that we have no forward references left. If so, there was a goto // or address of a label taken, but no definition of it. Label fwd // definitions are indicated with a null substmt which is also not a resolved // MS inline assembly label name. bool Diagnose = false; if (L->isMSAsmLabel()) Diagnose = !L->isResolvedMSAsmLabel(); else Diagnose = L->getStmt() == nullptr; if (Diagnose) S.Diag(L->getLocation(), diag::err_undeclared_label_use) <getDeclName(); } void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { S->mergeNRVOIntoParent(); if (S->decl_empty()) return; assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) && "Scope shouldn't contain decls!"); for (auto *TmpD : S->decls()) { assert(TmpD && "This decl didn't get pushed??"); assert(isa(TmpD) && "Decl isn't NamedDecl?"); NamedDecl *D = cast(TmpD); - if (!D->getDeclName()) continue; - // Diagnose unused variables in this scope. if (!S->hasUnrecoverableErrorOccurred()) { DiagnoseUnusedDecl(D); if (const auto *RD = dyn_cast(D)) DiagnoseUnusedNestedTypedefs(RD); } + if (!D->getDeclName()) continue; + // If this was a forward reference to a label, verify it was defined. if (LabelDecl *LD = dyn_cast(D)) CheckPoppedLabel(LD, *this); // Remove this name from our lexical scope, and warn on it if we haven't // already. IdResolver.RemoveDecl(D); auto ShadowI = ShadowingDecls.find(D); if (ShadowI != ShadowingDecls.end()) { if (const auto *FD = dyn_cast(ShadowI->second)) { Diag(D->getLocation(), diag::warn_ctor_parm_shadows_field) << D << FD << FD->getParent(); Diag(FD->getLocation(), diag::note_previous_declaration); } ShadowingDecls.erase(ShadowI); } } } /// \brief Look for an Objective-C class in the translation unit. /// /// \param Id The name of the Objective-C class we're looking for. If /// typo-correction fixes this name, the Id will be updated /// to the fixed name. /// /// \param IdLoc The location of the name in the translation unit. /// /// \param DoTypoCorrection If true, this routine will attempt typo correction /// if there is no class with the given name. /// /// \returns The declaration of the named Objective-C class, or NULL if the /// class could not be found. ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, SourceLocation IdLoc, bool DoTypoCorrection) { // The third "scope" argument is 0 since we aren't enabling lazy built-in // creation from this context. NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName); if (!IDecl && DoTypoCorrection) { // Perform typo correction at the given location, but only if we // find an Objective-C class name. if (TypoCorrection C = CorrectTypo( DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName, TUScope, nullptr, llvm::make_unique>(), CTK_ErrorRecovery)) { diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id); IDecl = C.getCorrectionDeclAs(); Id = IDecl->getIdentifier(); } } ObjCInterfaceDecl *Def = dyn_cast_or_null(IDecl); // This routine must always return a class definition, if any. if (Def && Def->getDefinition()) Def = Def->getDefinition(); return Def; } /// getNonFieldDeclScope - Retrieves the innermost scope, starting /// from S, where a non-field would be declared. This routine copes /// with the difference between C and C++ scoping rules in structs and /// unions. For example, the following code is well-formed in C but /// ill-formed in C++: /// @code /// struct S6 { /// enum { BAR } e; /// }; /// /// void test_S6() { /// struct S6 a; /// a.e = BAR; /// } /// @endcode /// For the declaration of BAR, this routine will return a different /// scope. The scope S will be the scope of the unnamed enumeration /// within S6. In C++, this routine will return the scope associated /// with S6, because the enumeration's scope is a transparent /// context but structures can contain non-field names. In C, this /// routine will return the translation unit scope, since the /// enumeration's scope is a transparent context and structures cannot /// contain non-field names. Scope *Sema::getNonFieldDeclScope(Scope *S) { while (((S->getFlags() & Scope::DeclScope) == 0) || (S->getEntity() && S->getEntity()->isTransparentContext()) || (S->isClassScope() && !getLangOpts().CPlusPlus)) S = S->getParent(); return S; } /// \brief Looks up the declaration of "struct objc_super" and /// saves it for later use in building builtin declaration of /// objc_msgSendSuper and objc_msgSendSuper_stret. If no such /// pre-existing declaration exists no action takes place. static void LookupPredefedObjCSuperType(Sema &ThisSema, Scope *S, IdentifierInfo *II) { if (!II->isStr("objc_msgSendSuper")) return; ASTContext &Context = ThisSema.Context; LookupResult Result(ThisSema, &Context.Idents.get("objc_super"), SourceLocation(), Sema::LookupTagName); ThisSema.LookupName(Result, S); if (Result.getResultKind() == LookupResult::Found) if (const TagDecl *TD = Result.getAsSingle()) Context.setObjCSuperType(Context.getTagDeclType(TD)); } static StringRef getHeaderName(ASTContext::GetBuiltinTypeError Error) { switch (Error) { case ASTContext::GE_None: return ""; case ASTContext::GE_Missing_stdio: return "stdio.h"; case ASTContext::GE_Missing_setjmp: return "setjmp.h"; case ASTContext::GE_Missing_ucontext: return "ucontext.h"; } llvm_unreachable("unhandled error kind"); } /// LazilyCreateBuiltin - The specified Builtin-ID was first used at /// file scope. lazily create a decl for it. ForRedeclaration is true /// if we're creating this built-in in anticipation of redeclaring the /// built-in. NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S, bool ForRedeclaration, SourceLocation Loc) { LookupPredefedObjCSuperType(*this, S, II); ASTContext::GetBuiltinTypeError Error; QualType R = Context.GetBuiltinType(ID, Error); if (Error) { if (ForRedeclaration) Diag(Loc, diag::warn_implicit_decl_requires_sysheader) << getHeaderName(Error) << Context.BuiltinInfo.getName(ID); return nullptr; } if (!ForRedeclaration && (Context.BuiltinInfo.isPredefinedLibFunction(ID) || Context.BuiltinInfo.isHeaderDependentFunction(ID))) { Diag(Loc, diag::ext_implicit_lib_function_decl) << Context.BuiltinInfo.getName(ID) << R; if (Context.BuiltinInfo.getHeaderName(ID) && !Diags.isIgnored(diag::ext_implicit_lib_function_decl, Loc)) Diag(Loc, diag::note_include_header_or_declare) << Context.BuiltinInfo.getHeaderName(ID) << Context.BuiltinInfo.getName(ID); } if (R.isNull()) return nullptr; DeclContext *Parent = Context.getTranslationUnitDecl(); if (getLangOpts().CPlusPlus) { LinkageSpecDecl *CLinkageDecl = LinkageSpecDecl::Create(Context, Parent, Loc, Loc, LinkageSpecDecl::lang_c, false); CLinkageDecl->setImplicit(); Parent->addDecl(CLinkageDecl); Parent = CLinkageDecl; } FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, R, /*TInfo=*/nullptr, SC_Extern, false, R->isFunctionProtoType()); New->setImplicit(); // Create Decl objects for each parameter, adding them to the // FunctionDecl. if (const FunctionProtoType *FT = dyn_cast(R)) { SmallVector Params; for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { ParmVarDecl *parm = ParmVarDecl::Create(Context, New, SourceLocation(), SourceLocation(), nullptr, FT->getParamType(i), /*TInfo=*/nullptr, SC_None, nullptr); parm->setScopeInfo(0, i); Params.push_back(parm); } New->setParams(Params); } AddKnownFunctionAttributes(New); RegisterLocallyScopedExternCDecl(New, S); // TUScope is the translation-unit scope to insert this function into. // FIXME: This is hideous. We need to teach PushOnScopeChains to // relate Scopes to DeclContexts, and probably eliminate CurContext // entirely, but we're not there yet. DeclContext *SavedContext = CurContext; CurContext = Parent; PushOnScopeChains(New, TUScope); CurContext = SavedContext; return New; } /// Typedef declarations don't have linkage, but they still denote the same /// entity if their types are the same. /// FIXME: This is notionally doing the same thing as ASTReaderDecl's /// isSameEntity. static void filterNonConflictingPreviousTypedefDecls(Sema &S, TypedefNameDecl *Decl, LookupResult &Previous) { // This is only interesting when modules are enabled. if (!S.getLangOpts().Modules && !S.getLangOpts().ModulesLocalVisibility) return; // Empty sets are uninteresting. if (Previous.empty()) return; LookupResult::Filter Filter = Previous.makeFilter(); while (Filter.hasNext()) { NamedDecl *Old = Filter.next(); // Non-hidden declarations are never ignored. if (S.isVisible(Old)) continue; // Declarations of the same entity are not ignored, even if they have // different linkages. if (auto *OldTD = dyn_cast(Old)) { if (S.Context.hasSameType(OldTD->getUnderlyingType(), Decl->getUnderlyingType())) continue; // If both declarations give a tag declaration a typedef name for linkage // purposes, then they declare the same entity. if (OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true) && Decl->getAnonDeclWithTypedefName()) continue; } Filter.erase(); } Filter.done(); } bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { QualType OldType; if (TypedefNameDecl *OldTypedef = dyn_cast(Old)) OldType = OldTypedef->getUnderlyingType(); else OldType = Context.getTypeDeclType(Old); QualType NewType = New->getUnderlyingType(); if (NewType->isVariablyModifiedType()) { // Must not redefine a typedef with a variably-modified type. int Kind = isa(Old) ? 1 : 0; Diag(New->getLocation(), diag::err_redefinition_variably_modified_typedef) << Kind << NewType; if (Old->getLocation().isValid()) notePreviousDefinition(Old, New->getLocation()); New->setInvalidDecl(); return true; } if (OldType != NewType && !OldType->isDependentType() && !NewType->isDependentType() && !Context.hasSameType(OldType, NewType)) { int Kind = isa(Old) ? 1 : 0; Diag(New->getLocation(), diag::err_redefinition_different_typedef) << Kind << NewType << OldType; if (Old->getLocation().isValid()) notePreviousDefinition(Old, New->getLocation()); New->setInvalidDecl(); return true; } return false; } /// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the /// same name and scope as a previous declaration 'Old'. Figure out /// how to resolve this situation, merging decls or emitting /// diagnostics as appropriate. If there was an error, set New to be invalid. /// void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, LookupResult &OldDecls) { // If the new decl is known invalid already, don't bother doing any // merging checks. if (New->isInvalidDecl()) return; // Allow multiple definitions for ObjC built-in typedefs. // FIXME: Verify the underlying types are equivalent! if (getLangOpts().ObjC1) { const IdentifierInfo *TypeID = New->getIdentifier(); switch (TypeID->getLength()) { default: break; case 2: { if (!TypeID->isStr("id")) break; QualType T = New->getUnderlyingType(); if (!T->isPointerType()) break; if (!T->isVoidPointerType()) { QualType PT = T->getAs()->getPointeeType(); if (!PT->isStructureType()) break; } Context.setObjCIdRedefinitionType(T); // Install the built-in type for 'id', ignoring the current definition. New->setTypeForDecl(Context.getObjCIdType().getTypePtr()); return; } case 5: if (!TypeID->isStr("Class")) break; Context.setObjCClassRedefinitionType(New->getUnderlyingType()); // Install the built-in type for 'Class', ignoring the current definition. New->setTypeForDecl(Context.getObjCClassType().getTypePtr()); return; case 3: if (!TypeID->isStr("SEL")) break; Context.setObjCSelRedefinitionType(New->getUnderlyingType()); // Install the built-in type for 'SEL', ignoring the current definition. New->setTypeForDecl(Context.getObjCSelType().getTypePtr()); return; } // Fall through - the typedef name was not a builtin type. } // Verify the old decl was also a type. TypeDecl *Old = OldDecls.getAsSingle(); if (!Old) { Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); NamedDecl *OldD = OldDecls.getRepresentativeDecl(); if (OldD->getLocation().isValid()) notePreviousDefinition(OldD, New->getLocation()); return New->setInvalidDecl(); } // If the old declaration is invalid, just give up here. if (Old->isInvalidDecl()) return New->setInvalidDecl(); if (auto *OldTD = dyn_cast(Old)) { auto *OldTag = OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true); auto *NewTag = New->getAnonDeclWithTypedefName(); NamedDecl *Hidden = nullptr; if (OldTag && NewTag && OldTag->getCanonicalDecl() != NewTag->getCanonicalDecl() && !hasVisibleDefinition(OldTag, &Hidden)) { // There is a definition of this tag, but it is not visible. Use it // instead of our tag. New->setTypeForDecl(OldTD->getTypeForDecl()); if (OldTD->isModed()) New->setModedTypeSourceInfo(OldTD->getTypeSourceInfo(), OldTD->getUnderlyingType()); else New->setTypeSourceInfo(OldTD->getTypeSourceInfo()); // Make the old tag definition visible. makeMergedDefinitionVisible(Hidden); // If this was an unscoped enumeration, yank all of its enumerators // out of the scope. if (isa(NewTag)) { Scope *EnumScope = getNonFieldDeclScope(S); for (auto *D : NewTag->decls()) { auto *ED = cast(D); assert(EnumScope->isDeclScope(ED)); EnumScope->RemoveDecl(ED); IdResolver.RemoveDecl(ED); ED->getLexicalDeclContext()->removeDecl(ED); } } } } // If the typedef types are not identical, reject them in all languages and // with any extensions enabled. if (isIncompatibleTypedef(Old, New)) return; // The types match. Link up the redeclaration chain and merge attributes if // the old declaration was a typedef. if (TypedefNameDecl *Typedef = dyn_cast(Old)) { New->setPreviousDecl(Typedef); mergeDeclAttributes(New, Old); } if (getLangOpts().MicrosoftExt) return; if (getLangOpts().CPlusPlus) { // C++ [dcl.typedef]p2: // In a given non-class scope, a typedef specifier can be used to // redefine the name of any type declared in that scope to refer // to the type to which it already refers. if (!isa(CurContext)) return; // C++0x [dcl.typedef]p4: // In a given class scope, a typedef specifier can be used to redefine // any class-name declared in that scope that is not also a typedef-name // to refer to the type to which it already refers. // // This wording came in via DR424, which was a correction to the // wording in DR56, which accidentally banned code like: // // struct S { // typedef struct A { } A; // }; // // in the C++03 standard. We implement the C++0x semantics, which // allow the above but disallow // // struct S { // typedef int I; // typedef int I; // }; // // since that was the intent of DR56. if (!isa(Old)) return; Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName(); notePreviousDefinition(Old, New->getLocation()); return New->setInvalidDecl(); } // Modules always permit redefinition of typedefs, as does C11. if (getLangOpts().Modules || getLangOpts().C11) return; // If we have a redefinition of a typedef in C, emit a warning. This warning // is normally mapped to an error, but can be controlled with // -Wtypedef-redefinition. If either the original or the redefinition is // in a system header, don't emit this for compatibility with GCC. if (getDiagnostics().getSuppressSystemWarnings() && // Some standard types are defined implicitly in Clang (e.g. OpenCL). (Old->isImplicit() || Context.getSourceManager().isInSystemHeader(Old->getLocation()) || Context.getSourceManager().isInSystemHeader(New->getLocation()))) return; Diag(New->getLocation(), diag::ext_redefinition_of_typedef) << New->getDeclName(); notePreviousDefinition(Old, New->getLocation()); } /// DeclhasAttr - returns true if decl Declaration already has the target /// attribute. static bool DeclHasAttr(const Decl *D, const Attr *A) { const OwnershipAttr *OA = dyn_cast(A); const AnnotateAttr *Ann = dyn_cast(A); for (const auto *i : D->attrs()) if (i->getKind() == A->getKind()) { if (Ann) { if (Ann->getAnnotation() == cast(i)->getAnnotation()) return true; continue; } // FIXME: Don't hardcode this check if (OA && isa(i)) return OA->getOwnKind() == cast(i)->getOwnKind(); return true; } return false; } static bool isAttributeTargetADefinition(Decl *D) { if (VarDecl *VD = dyn_cast(D)) return VD->isThisDeclarationADefinition(); if (TagDecl *TD = dyn_cast(D)) return TD->isCompleteDefinition() || TD->isBeingDefined(); return true; } /// Merge alignment attributes from \p Old to \p New, taking into account the /// special semantics of C11's _Alignas specifier and C++11's alignas attribute. /// /// \return \c true if any attributes were added to \p New. static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) { // Look for alignas attributes on Old, and pick out whichever attribute // specifies the strictest alignment requirement. AlignedAttr *OldAlignasAttr = nullptr; AlignedAttr *OldStrictestAlignAttr = nullptr; unsigned OldAlign = 0; for (auto *I : Old->specific_attrs()) { // FIXME: We have no way of representing inherited dependent alignments // in a case like: // template struct alignas(A) X; // template struct alignas(B) X {}; // For now, we just ignore any alignas attributes which are not on the // definition in such a case. if (I->isAlignmentDependent()) return false; if (I->isAlignas()) OldAlignasAttr = I; unsigned Align = I->getAlignment(S.Context); if (Align > OldAlign) { OldAlign = Align; OldStrictestAlignAttr = I; } } // Look for alignas attributes on New. AlignedAttr *NewAlignasAttr = nullptr; unsigned NewAlign = 0; for (auto *I : New->specific_attrs()) { if (I->isAlignmentDependent()) return false; if (I->isAlignas()) NewAlignasAttr = I; unsigned Align = I->getAlignment(S.Context); if (Align > NewAlign) NewAlign = Align; } if (OldAlignasAttr && NewAlignasAttr && OldAlign != NewAlign) { // Both declarations have 'alignas' attributes. We require them to match. // C++11 [dcl.align]p6 and C11 6.7.5/7 both come close to saying this, but // fall short. (If two declarations both have alignas, they must both match // every definition, and so must match each other if there is a definition.) // If either declaration only contains 'alignas(0)' specifiers, then it // specifies the natural alignment for the type. if (OldAlign == 0 || NewAlign == 0) { QualType Ty; if (ValueDecl *VD = dyn_cast(New)) Ty = VD->getType(); else Ty = S.Context.getTagDeclType(cast(New)); if (OldAlign == 0) OldAlign = S.Context.getTypeAlign(Ty); if (NewAlign == 0) NewAlign = S.Context.getTypeAlign(Ty); } if (OldAlign != NewAlign) { S.Diag(NewAlignasAttr->getLocation(), diag::err_alignas_mismatch) << (unsigned)S.Context.toCharUnitsFromBits(OldAlign).getQuantity() << (unsigned)S.Context.toCharUnitsFromBits(NewAlign).getQuantity(); S.Diag(OldAlignasAttr->getLocation(), diag::note_previous_declaration); } } if (OldAlignasAttr && !NewAlignasAttr && isAttributeTargetADefinition(New)) { // C++11 [dcl.align]p6: // if any declaration of an entity has an alignment-specifier, // every defining declaration of that entity shall specify an // equivalent alignment. // C11 6.7.5/7: // If the definition of an object does not have an alignment // specifier, any other declaration of that object shall also // have no alignment specifier. S.Diag(New->getLocation(), diag::err_alignas_missing_on_definition) << OldAlignasAttr; S.Diag(OldAlignasAttr->getLocation(), diag::note_alignas_on_declaration) << OldAlignasAttr; } bool AnyAdded = false; // Ensure we have an attribute representing the strictest alignment. if (OldAlign > NewAlign) { AlignedAttr *Clone = OldStrictestAlignAttr->clone(S.Context); Clone->setInherited(true); New->addAttr(Clone); AnyAdded = true; } // Ensure we have an alignas attribute if the old declaration had one. if (OldAlignasAttr && !NewAlignasAttr && !(AnyAdded && OldStrictestAlignAttr->isAlignas())) { AlignedAttr *Clone = OldAlignasAttr->clone(S.Context); Clone->setInherited(true); New->addAttr(Clone); AnyAdded = true; } return AnyAdded; } static bool mergeDeclAttribute(Sema &S, NamedDecl *D, const InheritableAttr *Attr, Sema::AvailabilityMergeKind AMK) { // This function copies an attribute Attr from a previous declaration to the // new declaration D if the new declaration doesn't itself have that attribute // yet or if that attribute allows duplicates. // If you're adding a new attribute that requires logic different from // "use explicit attribute on decl if present, else use attribute from // previous decl", for example if the attribute needs to be consistent // between redeclarations, you need to call a custom merge function here. InheritableAttr *NewAttr = nullptr; unsigned AttrSpellingListIndex = Attr->getSpellingListIndex(); if (const auto *AA = dyn_cast(Attr)) NewAttr = S.mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(), AA->isImplicit(), AA->getIntroduced(), AA->getDeprecated(), AA->getObsoleted(), AA->getUnavailable(), AA->getMessage(), AA->getStrict(), AA->getReplacement(), AMK, AttrSpellingListIndex); else if (const auto *VA = dyn_cast(Attr)) NewAttr = S.mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility(), AttrSpellingListIndex); else if (const auto *VA = dyn_cast(Attr)) NewAttr = S.mergeTypeVisibilityAttr(D, VA->getRange(), VA->getVisibility(), AttrSpellingListIndex); else if (const auto *ImportA = dyn_cast(Attr)) NewAttr = S.mergeDLLImportAttr(D, ImportA->getRange(), AttrSpellingListIndex); else if (const auto *ExportA = dyn_cast(Attr)) NewAttr = S.mergeDLLExportAttr(D, ExportA->getRange(), AttrSpellingListIndex); else if (const auto *FA = dyn_cast(Attr)) NewAttr = S.mergeFormatAttr(D, FA->getRange(), FA->getType(), FA->getFormatIdx(), FA->getFirstArg(), AttrSpellingListIndex); else if (const auto *SA = dyn_cast(Attr)) NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(), AttrSpellingListIndex); else if (const auto *IA = dyn_cast(Attr)) NewAttr = S.mergeMSInheritanceAttr(D, IA->getRange(), IA->getBestCase(), AttrSpellingListIndex, IA->getSemanticSpelling()); else if (const auto *AA = dyn_cast(Attr)) NewAttr = S.mergeAlwaysInlineAttr(D, AA->getRange(), &S.Context.Idents.get(AA->getSpelling()), AttrSpellingListIndex); else if (S.getLangOpts().CUDA && isa(D) && (isa(Attr) || isa(Attr) || isa(Attr))) { // CUDA target attributes are part of function signature for // overloading purposes and must not be merged. return false; } else if (const auto *MA = dyn_cast(Attr)) NewAttr = S.mergeMinSizeAttr(D, MA->getRange(), AttrSpellingListIndex); else if (const auto *OA = dyn_cast(Attr)) NewAttr = S.mergeOptimizeNoneAttr(D, OA->getRange(), AttrSpellingListIndex); else if (const auto *InternalLinkageA = dyn_cast(Attr)) NewAttr = S.mergeInternalLinkageAttr( D, InternalLinkageA->getRange(), &S.Context.Idents.get(InternalLinkageA->getSpelling()), AttrSpellingListIndex); else if (const auto *CommonA = dyn_cast(Attr)) NewAttr = S.mergeCommonAttr(D, CommonA->getRange(), &S.Context.Idents.get(CommonA->getSpelling()), AttrSpellingListIndex); else if (isa(Attr)) // AlignedAttrs are handled separately, because we need to handle all // such attributes on a declaration at the same time. NewAttr = nullptr; else if ((isa(Attr) || isa(Attr)) && (AMK == Sema::AMK_Override || AMK == Sema::AMK_ProtocolImplementation)) NewAttr = nullptr; else if (const auto *UA = dyn_cast(Attr)) NewAttr = S.mergeUuidAttr(D, UA->getRange(), AttrSpellingListIndex, UA->getGuid()); else if (Attr->duplicatesAllowed() || !DeclHasAttr(D, Attr)) NewAttr = cast(Attr->clone(S.Context)); if (NewAttr) { NewAttr->setInherited(true); D->addAttr(NewAttr); if (isa(NewAttr)) S.Consumer.AssignInheritanceModel(cast(D)); return true; } return false; } static const NamedDecl *getDefinition(const Decl *D) { if (const TagDecl *TD = dyn_cast(D)) return TD->getDefinition(); if (const VarDecl *VD = dyn_cast(D)) { const VarDecl *Def = VD->getDefinition(); if (Def) return Def; return VD->getActingDefinition(); } if (const FunctionDecl *FD = dyn_cast(D)) return FD->getDefinition(); return nullptr; } static bool hasAttribute(const Decl *D, attr::Kind Kind) { for (const auto *Attribute : D->attrs()) if (Attribute->getKind() == Kind) return true; return false; } /// checkNewAttributesAfterDef - If we already have a definition, check that /// there are no new attributes in this declaration. static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { if (!New->hasAttrs()) return; const NamedDecl *Def = getDefinition(Old); if (!Def || Def == New) return; AttrVec &NewAttributes = New->getAttrs(); for (unsigned I = 0, E = NewAttributes.size(); I != E;) { const Attr *NewAttribute = NewAttributes[I]; if (isa(NewAttribute) || isa(NewAttribute)) { if (FunctionDecl *FD = dyn_cast(New)) { Sema::SkipBodyInfo SkipBody; S.CheckForFunctionRedefinition(FD, cast(Def), &SkipBody); // If we're skipping this definition, drop the "alias" attribute. if (SkipBody.ShouldSkip) { NewAttributes.erase(NewAttributes.begin() + I); --E; continue; } } else { VarDecl *VD = cast(New); unsigned Diag = cast(Def)->isThisDeclarationADefinition() == VarDecl::TentativeDefinition ? diag::err_alias_after_tentative : diag::err_redefinition; S.Diag(VD->getLocation(), Diag) << VD->getDeclName(); if (Diag == diag::err_redefinition) S.notePreviousDefinition(Def, VD->getLocation()); else S.Diag(Def->getLocation(), diag::note_previous_definition); VD->setInvalidDecl(); } ++I; continue; } if (const VarDecl *VD = dyn_cast(Def)) { // Tentative definitions are only interesting for the alias check above. if (VD->isThisDeclarationADefinition() != VarDecl::Definition) { ++I; continue; } } if (hasAttribute(Def, NewAttribute->getKind())) { ++I; continue; // regular attr merging will take care of validating this. } if (isa(NewAttribute)) { // C's _Noreturn is allowed to be added to a function after it is defined. ++I; continue; } else if (const AlignedAttr *AA = dyn_cast(NewAttribute)) { if (AA->isAlignas()) { // C++11 [dcl.align]p6: // if any declaration of an entity has an alignment-specifier, // every defining declaration of that entity shall specify an // equivalent alignment. // C11 6.7.5/7: // If the definition of an object does not have an alignment // specifier, any other declaration of that object shall also // have no alignment specifier. S.Diag(Def->getLocation(), diag::err_alignas_missing_on_definition) << AA; S.Diag(NewAttribute->getLocation(), diag::note_alignas_on_declaration) << AA; NewAttributes.erase(NewAttributes.begin() + I); --E; continue; } } S.Diag(NewAttribute->getLocation(), diag::warn_attribute_precede_definition); S.Diag(Def->getLocation(), diag::note_previous_definition); NewAttributes.erase(NewAttributes.begin() + I); --E; } } /// mergeDeclAttributes - Copy attributes from the Old decl to the New one. void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, AvailabilityMergeKind AMK) { if (UsedAttr *OldAttr = Old->getMostRecentDecl()->getAttr()) { UsedAttr *NewAttr = OldAttr->clone(Context); NewAttr->setInherited(true); New->addAttr(NewAttr); } if (!Old->hasAttrs() && !New->hasAttrs()) return; // Attributes declared post-definition are currently ignored. checkNewAttributesAfterDef(*this, New, Old); if (AsmLabelAttr *NewA = New->getAttr()) { if (AsmLabelAttr *OldA = Old->getAttr()) { if (OldA->getLabel() != NewA->getLabel()) { // This redeclaration changes __asm__ label. Diag(New->getLocation(), diag::err_different_asm_label); Diag(OldA->getLocation(), diag::note_previous_declaration); } } else if (Old->isUsed()) { // This redeclaration adds an __asm__ label to a declaration that has // already been ODR-used. Diag(New->getLocation(), diag::err_late_asm_label_name) << isa(Old) << New->getAttr()->getRange(); } } // Re-declaration cannot add abi_tag's. if (const auto *NewAbiTagAttr = New->getAttr()) { if (const auto *OldAbiTagAttr = Old->getAttr()) { for (const auto &NewTag : NewAbiTagAttr->tags()) { if (std::find(OldAbiTagAttr->tags_begin(), OldAbiTagAttr->tags_end(), NewTag) == OldAbiTagAttr->tags_end()) { Diag(NewAbiTagAttr->getLocation(), diag::err_new_abi_tag_on_redeclaration) << NewTag; Diag(OldAbiTagAttr->getLocation(), diag::note_previous_declaration); } } } else { Diag(NewAbiTagAttr->getLocation(), diag::err_abi_tag_on_redeclaration); Diag(Old->getLocation(), diag::note_previous_declaration); } } if (!Old->hasAttrs()) return; bool foundAny = New->hasAttrs(); // Ensure that any moving of objects within the allocated map is done before // we process them. if (!foundAny) New->setAttrs(AttrVec()); for (auto *I : Old->specific_attrs()) { // Ignore deprecated/unavailable/availability attributes if requested. AvailabilityMergeKind LocalAMK = AMK_None; if (isa(I) || isa(I) || isa(I)) { switch (AMK) { case AMK_None: continue; case AMK_Redeclaration: case AMK_Override: case AMK_ProtocolImplementation: LocalAMK = AMK; break; } } // Already handled. if (isa(I)) continue; if (mergeDeclAttribute(*this, New, I, LocalAMK)) foundAny = true; } if (mergeAlignedAttrs(*this, New, Old)) foundAny = true; if (!foundAny) New->dropAttrs(); } /// mergeParamDeclAttributes - Copy attributes from the old parameter /// to the new one. static void mergeParamDeclAttributes(ParmVarDecl *newDecl, const ParmVarDecl *oldDecl, Sema &S) { // C++11 [dcl.attr.depend]p2: // The first declaration of a function shall specify the // carries_dependency attribute for its declarator-id if any declaration // of the function specifies the carries_dependency attribute. const CarriesDependencyAttr *CDA = newDecl->getAttr(); if (CDA && !oldDecl->hasAttr()) { S.Diag(CDA->getLocation(), diag::err_carries_dependency_missing_on_first_decl) << 1/*Param*/; // Find the first declaration of the parameter. // FIXME: Should we build redeclaration chains for function parameters? const FunctionDecl *FirstFD = cast(oldDecl->getDeclContext())->getFirstDecl(); const ParmVarDecl *FirstVD = FirstFD->getParamDecl(oldDecl->getFunctionScopeIndex()); S.Diag(FirstVD->getLocation(), diag::note_carries_dependency_missing_first_decl) << 1/*Param*/; } if (!oldDecl->hasAttrs()) return; bool foundAny = newDecl->hasAttrs(); // Ensure that any moving of objects within the allocated map is // done before we process them. if (!foundAny) newDecl->setAttrs(AttrVec()); for (const auto *I : oldDecl->specific_attrs()) { if (!DeclHasAttr(newDecl, I)) { InheritableAttr *newAttr = cast(I->clone(S.Context)); newAttr->setInherited(true); newDecl->addAttr(newAttr); foundAny = true; } } if (!foundAny) newDecl->dropAttrs(); } static void mergeParamDeclTypes(ParmVarDecl *NewParam, const ParmVarDecl *OldParam, Sema &S) { if (auto Oldnullability = OldParam->getType()->getNullability(S.Context)) { if (auto Newnullability = NewParam->getType()->getNullability(S.Context)) { if (*Oldnullability != *Newnullability) { S.Diag(NewParam->getLocation(), diag::warn_mismatched_nullability_attr) << DiagNullabilityKind( *Newnullability, ((NewParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0)) << DiagNullabilityKind( *Oldnullability, ((OldParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0)); S.Diag(OldParam->getLocation(), diag::note_previous_declaration); } } else { QualType NewT = NewParam->getType(); NewT = S.Context.getAttributedType( AttributedType::getNullabilityAttrKind(*Oldnullability), NewT, NewT); NewParam->setType(NewT); } } } namespace { /// Used in MergeFunctionDecl to keep track of function parameters in /// C. struct GNUCompatibleParamWarning { ParmVarDecl *OldParm; ParmVarDecl *NewParm; QualType PromotedType; }; } // end anonymous namespace /// getSpecialMember - get the special member enum for a method. Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) { if (const CXXConstructorDecl *Ctor = dyn_cast(MD)) { if (Ctor->isDefaultConstructor()) return Sema::CXXDefaultConstructor; if (Ctor->isCopyConstructor()) return Sema::CXXCopyConstructor; if (Ctor->isMoveConstructor()) return Sema::CXXMoveConstructor; } else if (isa(MD)) { return Sema::CXXDestructor; } else if (MD->isCopyAssignmentOperator()) { return Sema::CXXCopyAssignment; } else if (MD->isMoveAssignmentOperator()) { return Sema::CXXMoveAssignment; } return Sema::CXXInvalid; } // Determine whether the previous declaration was a definition, implicit // declaration, or a declaration. template static std::pair getNoteDiagForInvalidRedeclaration(const T *Old, const T *New) { diag::kind PrevDiag; SourceLocation OldLocation = Old->getLocation(); if (Old->isThisDeclarationADefinition()) PrevDiag = diag::note_previous_definition; else if (Old->isImplicit()) { PrevDiag = diag::note_previous_implicit_declaration; if (OldLocation.isInvalid()) OldLocation = New->getLocation(); } else PrevDiag = diag::note_previous_declaration; return std::make_pair(PrevDiag, OldLocation); } /// canRedefineFunction - checks if a function can be redefined. Currently, /// only extern inline functions can be redefined, and even then only in /// GNU89 mode. static bool canRedefineFunction(const FunctionDecl *FD, const LangOptions& LangOpts) { return ((FD->hasAttr() || LangOpts.GNUInline) && !LangOpts.CPlusPlus && FD->isInlineSpecified() && FD->getStorageClass() == SC_Extern); } const AttributedType *Sema::getCallingConvAttributedType(QualType T) const { const AttributedType *AT = T->getAs(); while (AT && !AT->isCallingConv()) AT = AT->getModifiedType()->getAs(); return AT; } template static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) { const DeclContext *DC = Old->getDeclContext(); if (DC->isRecord()) return false; LanguageLinkage OldLinkage = Old->getLanguageLinkage(); if (OldLinkage == CXXLanguageLinkage && New->isInExternCContext()) return true; if (OldLinkage == CLanguageLinkage && New->isInExternCXXContext()) return true; return false; } template static bool isExternC(T *D) { return D->isExternC(); } static bool isExternC(VarTemplateDecl *) { return false; } /// \brief Check whether a redeclaration of an entity introduced by a /// using-declaration is valid, given that we know it's not an overload /// (nor a hidden tag declaration). template static bool checkUsingShadowRedecl(Sema &S, UsingShadowDecl *OldS, ExpectedDecl *New) { // C++11 [basic.scope.declarative]p4: // Given a set of declarations in a single declarative region, each of // which specifies the same unqualified name, // -- they shall all refer to the same entity, or all refer to functions // and function templates; or // -- exactly one declaration shall declare a class name or enumeration // name that is not a typedef name and the other declarations shall all // refer to the same variable or enumerator, or all refer to functions // and function templates; in this case the class name or enumeration // name is hidden (3.3.10). // C++11 [namespace.udecl]p14: // If a function declaration in namespace scope or block scope has the // same name and the same parameter-type-list as a function introduced // by a using-declaration, and the declarations do not declare the same // function, the program is ill-formed. auto *Old = dyn_cast(OldS->getTargetDecl()); if (Old && !Old->getDeclContext()->getRedeclContext()->Equals( New->getDeclContext()->getRedeclContext()) && !(isExternC(Old) && isExternC(New))) Old = nullptr; if (!Old) { S.Diag(New->getLocation(), diag::err_using_decl_conflict_reverse); S.Diag(OldS->getTargetDecl()->getLocation(), diag::note_using_decl_target); S.Diag(OldS->getUsingDecl()->getLocation(), diag::note_using_decl) << 0; return true; } return false; } static bool hasIdenticalPassObjectSizeAttrs(const FunctionDecl *A, const FunctionDecl *B) { assert(A->getNumParams() == B->getNumParams()); auto AttrEq = [](const ParmVarDecl *A, const ParmVarDecl *B) { const auto *AttrA = A->getAttr(); const auto *AttrB = B->getAttr(); if (AttrA == AttrB) return true; return AttrA && AttrB && AttrA->getType() == AttrB->getType(); }; return std::equal(A->param_begin(), A->param_end(), B->param_begin(), AttrEq); } /// MergeFunctionDecl - We just parsed a function 'New' from /// declarator D which has the same name and scope as a previous /// declaration 'Old'. Figure out how to resolve this situation, /// merging decls or emitting diagnostics as appropriate. /// /// In C++, New and Old must be declarations that are not /// overloaded. Use IsOverload to determine whether New and Old are /// overloaded, and to select the Old declaration that New should be /// merged with. /// /// Returns true if there was an error, false otherwise. bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S, bool MergeTypeWithOld) { // Verify the old decl was also a function. FunctionDecl *Old = OldD->getAsFunction(); if (!Old) { if (UsingShadowDecl *Shadow = dyn_cast(OldD)) { if (New->getFriendObjectKind()) { Diag(New->getLocation(), diag::err_using_decl_friend); Diag(Shadow->getTargetDecl()->getLocation(), diag::note_using_decl_target); Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) << 0; return true; } // Check whether the two declarations might declare the same function. if (checkUsingShadowRedecl(*this, Shadow, New)) return true; OldD = Old = cast(Shadow->getTargetDecl()); } else { Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); notePreviousDefinition(OldD, New->getLocation()); return true; } } // If the old declaration is invalid, just give up here. if (Old->isInvalidDecl()) return true; diag::kind PrevDiag; SourceLocation OldLocation; std::tie(PrevDiag, OldLocation) = getNoteDiagForInvalidRedeclaration(Old, New); // Don't complain about this if we're in GNU89 mode and the old function // is an extern inline function. // Don't complain about specializations. They are not supposed to have // storage classes. if (!isa(New) && !isa(Old) && New->getStorageClass() == SC_Static && Old->hasExternalFormalLinkage() && !New->getTemplateSpecializationInfo() && !canRedefineFunction(Old, getLangOpts())) { if (getLangOpts().MicrosoftExt) { Diag(New->getLocation(), diag::ext_static_non_static) << New; Diag(OldLocation, PrevDiag); } else { Diag(New->getLocation(), diag::err_static_non_static) << New; Diag(OldLocation, PrevDiag); return true; } } if (New->hasAttr() && !Old->hasAttr()) { Diag(New->getLocation(), diag::err_internal_linkage_redeclaration) << New->getDeclName(); notePreviousDefinition(Old, New->getLocation()); New->dropAttr(); } if (!getLangOpts().CPlusPlus) { bool OldOvl = Old->hasAttr(); if (OldOvl != New->hasAttr() && !Old->isImplicit()) { Diag(New->getLocation(), diag::err_attribute_overloadable_mismatch) << New << OldOvl; // Try our best to find a decl that actually has the overloadable // attribute for the note. In most cases (e.g. programs with only one // broken declaration/definition), this won't matter. // // FIXME: We could do this if we juggled some extra state in // OverloadableAttr, rather than just removing it. const Decl *DiagOld = Old; if (OldOvl) { auto OldIter = llvm::find_if(Old->redecls(), [](const Decl *D) { const auto *A = D->getAttr(); return A && !A->isImplicit(); }); // If we've implicitly added *all* of the overloadable attrs to this // chain, emitting a "previous redecl" note is pointless. DiagOld = OldIter == Old->redecls_end() ? nullptr : *OldIter; } if (DiagOld) Diag(DiagOld->getLocation(), diag::note_attribute_overloadable_prev_overload) << OldOvl; if (OldOvl) New->addAttr(OverloadableAttr::CreateImplicit(Context)); else New->dropAttr(); } } // If a function is first declared with a calling convention, but is later // declared or defined without one, all following decls assume the calling // convention of the first. // // It's OK if a function is first declared without a calling convention, // but is later declared or defined with the default calling convention. // // To test if either decl has an explicit calling convention, we look for // AttributedType sugar nodes on the type as written. If they are missing or // were canonicalized away, we assume the calling convention was implicit. // // Note also that we DO NOT return at this point, because we still have // other tests to run. QualType OldQType = Context.getCanonicalType(Old->getType()); QualType NewQType = Context.getCanonicalType(New->getType()); const FunctionType *OldType = cast(OldQType); const FunctionType *NewType = cast(NewQType); FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo(); FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo(); bool RequiresAdjustment = false; if (OldTypeInfo.getCC() != NewTypeInfo.getCC()) { FunctionDecl *First = Old->getFirstDecl(); const FunctionType *FT = First->getType().getCanonicalType()->castAs(); FunctionType::ExtInfo FI = FT->getExtInfo(); bool NewCCExplicit = getCallingConvAttributedType(New->getType()); if (!NewCCExplicit) { // Inherit the CC from the previous declaration if it was specified // there but not here. NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); RequiresAdjustment = true; } else { // Calling conventions aren't compatible, so complain. bool FirstCCExplicit = getCallingConvAttributedType(First->getType()); Diag(New->getLocation(), diag::err_cconv_change) << FunctionType::getNameForCallConv(NewTypeInfo.getCC()) << !FirstCCExplicit << (!FirstCCExplicit ? "" : FunctionType::getNameForCallConv(FI.getCC())); // Put the note on the first decl, since it is the one that matters. Diag(First->getLocation(), diag::note_previous_declaration); return true; } } // FIXME: diagnose the other way around? if (OldTypeInfo.getNoReturn() && !NewTypeInfo.getNoReturn()) { NewTypeInfo = NewTypeInfo.withNoReturn(true); RequiresAdjustment = true; } // Merge regparm attribute. if (OldTypeInfo.getHasRegParm() != NewTypeInfo.getHasRegParm() || OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) { if (NewTypeInfo.getHasRegParm()) { Diag(New->getLocation(), diag::err_regparm_mismatch) << NewType->getRegParmType() << OldType->getRegParmType(); Diag(OldLocation, diag::note_previous_declaration); return true; } NewTypeInfo = NewTypeInfo.withRegParm(OldTypeInfo.getRegParm()); RequiresAdjustment = true; } // Merge ns_returns_retained attribute. if (OldTypeInfo.getProducesResult() != NewTypeInfo.getProducesResult()) { if (NewTypeInfo.getProducesResult()) { Diag(New->getLocation(), diag::err_function_attribute_mismatch) << "'ns_returns_retained'"; Diag(OldLocation, diag::note_previous_declaration); return true; } NewTypeInfo = NewTypeInfo.withProducesResult(true); RequiresAdjustment = true; } if (OldTypeInfo.getNoCallerSavedRegs() != NewTypeInfo.getNoCallerSavedRegs()) { if (NewTypeInfo.getNoCallerSavedRegs()) { AnyX86NoCallerSavedRegistersAttr *Attr = New->getAttr(); Diag(New->getLocation(), diag::err_function_attribute_mismatch) << Attr; Diag(OldLocation, diag::note_previous_declaration); return true; } NewTypeInfo = NewTypeInfo.withNoCallerSavedRegs(true); RequiresAdjustment = true; } if (RequiresAdjustment) { const FunctionType *AdjustedType = New->getType()->getAs(); AdjustedType = Context.adjustFunctionType(AdjustedType, NewTypeInfo); New->setType(QualType(AdjustedType, 0)); NewQType = Context.getCanonicalType(New->getType()); NewType = cast(NewQType); } // If this redeclaration makes the function inline, we may need to add it to // UndefinedButUsed. if (!Old->isInlined() && New->isInlined() && !New->hasAttr() && !getLangOpts().GNUInline && Old->isUsed(false) && !Old->isDefined() && !New->isThisDeclarationADefinition()) UndefinedButUsed.insert(std::make_pair(Old->getCanonicalDecl(), SourceLocation())); // If this redeclaration makes it newly gnu_inline, we don't want to warn // about it. if (New->hasAttr() && Old->isInlined() && !Old->hasAttr()) { UndefinedButUsed.erase(Old->getCanonicalDecl()); } // If pass_object_size params don't match up perfectly, this isn't a valid // redeclaration. if (Old->getNumParams() > 0 && Old->getNumParams() == New->getNumParams() && !hasIdenticalPassObjectSizeAttrs(Old, New)) { Diag(New->getLocation(), diag::err_different_pass_object_size_params) << New->getDeclName(); Diag(OldLocation, PrevDiag) << Old << Old->getType(); return true; } if (getLangOpts().CPlusPlus) { // C++1z [over.load]p2 // Certain function declarations cannot be overloaded: // -- Function declarations that differ only in the return type, // the exception specification, or both cannot be overloaded. // Check the exception specifications match. This may recompute the type of // both Old and New if it resolved exception specifications, so grab the // types again after this. Because this updates the type, we do this before // any of the other checks below, which may update the "de facto" NewQType // but do not necessarily update the type of New. if (CheckEquivalentExceptionSpec(Old, New)) return true; OldQType = Context.getCanonicalType(Old->getType()); NewQType = Context.getCanonicalType(New->getType()); // Go back to the type source info to compare the declared return types, // per C++1y [dcl.type.auto]p13: // Redeclarations or specializations of a function or function template // with a declared return type that uses a placeholder type shall also // use that placeholder, not a deduced type. QualType OldDeclaredReturnType = (Old->getTypeSourceInfo() ? Old->getTypeSourceInfo()->getType()->castAs() : OldType)->getReturnType(); QualType NewDeclaredReturnType = (New->getTypeSourceInfo() ? New->getTypeSourceInfo()->getType()->castAs() : NewType)->getReturnType(); if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType) && !((NewQType->isDependentType() || OldQType->isDependentType()) && New->isLocalExternDecl())) { QualType ResQT; if (NewDeclaredReturnType->isObjCObjectPointerType() && OldDeclaredReturnType->isObjCObjectPointerType()) ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType); if (ResQT.isNull()) { if (New->isCXXClassMember() && New->isOutOfLine()) Diag(New->getLocation(), diag::err_member_def_does_not_match_ret_type) << New << New->getReturnTypeSourceRange(); else Diag(New->getLocation(), diag::err_ovl_diff_return_type) << New->getReturnTypeSourceRange(); Diag(OldLocation, PrevDiag) << Old << Old->getType() << Old->getReturnTypeSourceRange(); return true; } else NewQType = ResQT; } QualType OldReturnType = OldType->getReturnType(); QualType NewReturnType = cast(NewQType)->getReturnType(); if (OldReturnType != NewReturnType) { // If this function has a deduced return type and has already been // defined, copy the deduced value from the old declaration. AutoType *OldAT = Old->getReturnType()->getContainedAutoType(); if (OldAT && OldAT->isDeduced()) { New->setType( SubstAutoType(New->getType(), OldAT->isDependentType() ? Context.DependentTy : OldAT->getDeducedType())); NewQType = Context.getCanonicalType( SubstAutoType(NewQType, OldAT->isDependentType() ? Context.DependentTy : OldAT->getDeducedType())); } } const CXXMethodDecl *OldMethod = dyn_cast(Old); CXXMethodDecl *NewMethod = dyn_cast(New); if (OldMethod && NewMethod) { // Preserve triviality. NewMethod->setTrivial(OldMethod->isTrivial()); // MSVC allows explicit template specialization at class scope: // 2 CXXMethodDecls referring to the same function will be injected. // We don't want a redeclaration error. bool IsClassScopeExplicitSpecialization = OldMethod->isFunctionTemplateSpecialization() && NewMethod->isFunctionTemplateSpecialization(); bool isFriend = NewMethod->getFriendObjectKind(); if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord() && !IsClassScopeExplicitSpecialization) { // -- Member function declarations with the same name and the // same parameter types cannot be overloaded if any of them // is a static member function declaration. if (OldMethod->isStatic() != NewMethod->isStatic()) { Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member); Diag(OldLocation, PrevDiag) << Old << Old->getType(); return true; } // C++ [class.mem]p1: // [...] A member shall not be declared twice in the // member-specification, except that a nested class or member // class template can be declared and then later defined. if (!inTemplateInstantiation()) { unsigned NewDiag; if (isa(OldMethod)) NewDiag = diag::err_constructor_redeclared; else if (isa(NewMethod)) NewDiag = diag::err_destructor_redeclared; else if (isa(NewMethod)) NewDiag = diag::err_conv_function_redeclared; else NewDiag = diag::err_member_redeclared; Diag(New->getLocation(), NewDiag); } else { Diag(New->getLocation(), diag::err_member_redeclared_in_instantiation) << New << New->getType(); } Diag(OldLocation, PrevDiag) << Old << Old->getType(); return true; // Complain if this is an explicit declaration of a special // member that was initially declared implicitly. // // As an exception, it's okay to befriend such methods in order // to permit the implicit constructor/destructor/operator calls. } else if (OldMethod->isImplicit()) { if (isFriend) { NewMethod->setImplicit(); } else { Diag(NewMethod->getLocation(), diag::err_definition_of_implicitly_declared_member) << New << getSpecialMember(OldMethod); return true; } } else if (OldMethod->getFirstDecl()->isExplicitlyDefaulted() && !isFriend) { Diag(NewMethod->getLocation(), diag::err_definition_of_explicitly_defaulted_member) << getSpecialMember(OldMethod); return true; } } // C++11 [dcl.attr.noreturn]p1: // The first declaration of a function shall specify the noreturn // attribute if any declaration of that function specifies the noreturn // attribute. const CXX11NoReturnAttr *NRA = New->getAttr(); if (NRA && !Old->hasAttr()) { Diag(NRA->getLocation(), diag::err_noreturn_missing_on_first_decl); Diag(Old->getFirstDecl()->getLocation(), diag::note_noreturn_missing_first_decl); } // C++11 [dcl.attr.depend]p2: // The first declaration of a function shall specify the // carries_dependency attribute for its declarator-id if any declaration // of the function specifies the carries_dependency attribute. const CarriesDependencyAttr *CDA = New->getAttr(); if (CDA && !Old->hasAttr()) { Diag(CDA->getLocation(), diag::err_carries_dependency_missing_on_first_decl) << 0/*Function*/; Diag(Old->getFirstDecl()->getLocation(), diag::note_carries_dependency_missing_first_decl) << 0/*Function*/; } // (C++98 8.3.5p3): // All declarations for a function shall agree exactly in both the // return type and the parameter-type-list. // We also want to respect all the extended bits except noreturn. // noreturn should now match unless the old type info didn't have it. QualType OldQTypeForComparison = OldQType; if (!OldTypeInfo.getNoReturn() && NewTypeInfo.getNoReturn()) { auto *OldType = OldQType->castAs(); const FunctionType *OldTypeForComparison = Context.adjustFunctionType(OldType, OldTypeInfo.withNoReturn(true)); OldQTypeForComparison = QualType(OldTypeForComparison, 0); assert(OldQTypeForComparison.isCanonical()); } if (haveIncompatibleLanguageLinkages(Old, New)) { // As a special case, retain the language linkage from previous // declarations of a friend function as an extension. // // This liberal interpretation of C++ [class.friend]p3 matches GCC/MSVC // and is useful because there's otherwise no way to specify language // linkage within class scope. // // Check cautiously as the friend object kind isn't yet complete. if (New->getFriendObjectKind() != Decl::FOK_None) { Diag(New->getLocation(), diag::ext_retained_language_linkage) << New; Diag(OldLocation, PrevDiag); } else { Diag(New->getLocation(), diag::err_different_language_linkage) << New; Diag(OldLocation, PrevDiag); return true; } } if (OldQTypeForComparison == NewQType) return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld); if ((NewQType->isDependentType() || OldQType->isDependentType()) && New->isLocalExternDecl()) { // It's OK if we couldn't merge types for a local function declaraton // if either the old or new type is dependent. We'll merge the types // when we instantiate the function. return false; } // Fall through for conflicting redeclarations and redefinitions. } // C: Function types need to be compatible, not identical. This handles // duplicate function decls like "void f(int); void f(enum X);" properly. if (!getLangOpts().CPlusPlus && Context.typesAreCompatible(OldQType, NewQType)) { const FunctionType *OldFuncType = OldQType->getAs(); const FunctionType *NewFuncType = NewQType->getAs(); const FunctionProtoType *OldProto = nullptr; if (MergeTypeWithOld && isa(NewFuncType) && (OldProto = dyn_cast(OldFuncType))) { // The old declaration provided a function prototype, but the // new declaration does not. Merge in the prototype. assert(!OldProto->hasExceptionSpec() && "Exception spec in C"); SmallVector ParamTypes(OldProto->param_types()); NewQType = Context.getFunctionType(NewFuncType->getReturnType(), ParamTypes, OldProto->getExtProtoInfo()); New->setType(NewQType); New->setHasInheritedPrototype(); // Synthesize parameters with the same types. SmallVector Params; for (const auto &ParamType : OldProto->param_types()) { ParmVarDecl *Param = ParmVarDecl::Create(Context, New, SourceLocation(), SourceLocation(), nullptr, ParamType, /*TInfo=*/nullptr, SC_None, nullptr); Param->setScopeInfo(0, Params.size()); Param->setImplicit(); Params.push_back(Param); } New->setParams(Params); } return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld); } // GNU C permits a K&R definition to follow a prototype declaration // if the declared types of the parameters in the K&R definition // match the types in the prototype declaration, even when the // promoted types of the parameters from the K&R definition differ // from the types in the prototype. GCC then keeps the types from // the prototype. // // If a variadic prototype is followed by a non-variadic K&R definition, // the K&R definition becomes variadic. This is sort of an edge case, but // it's legal per the standard depending on how you read C99 6.7.5.3p15 and // C99 6.9.1p8. if (!getLangOpts().CPlusPlus && Old->hasPrototype() && !New->hasPrototype() && New->getType()->getAs() && Old->getNumParams() == New->getNumParams()) { SmallVector ArgTypes; SmallVector Warnings; const FunctionProtoType *OldProto = Old->getType()->getAs(); const FunctionProtoType *NewProto = New->getType()->getAs(); // Determine whether this is the GNU C extension. QualType MergedReturn = Context.mergeTypes(OldProto->getReturnType(), NewProto->getReturnType()); bool LooseCompatible = !MergedReturn.isNull(); for (unsigned Idx = 0, End = Old->getNumParams(); LooseCompatible && Idx != End; ++Idx) { ParmVarDecl *OldParm = Old->getParamDecl(Idx); ParmVarDecl *NewParm = New->getParamDecl(Idx); if (Context.typesAreCompatible(OldParm->getType(), NewProto->getParamType(Idx))) { ArgTypes.push_back(NewParm->getType()); } else if (Context.typesAreCompatible(OldParm->getType(), NewParm->getType(), /*CompareUnqualified=*/true)) { GNUCompatibleParamWarning Warn = { OldParm, NewParm, NewProto->getParamType(Idx) }; Warnings.push_back(Warn); ArgTypes.push_back(NewParm->getType()); } else LooseCompatible = false; } if (LooseCompatible) { for (unsigned Warn = 0; Warn < Warnings.size(); ++Warn) { Diag(Warnings[Warn].NewParm->getLocation(), diag::ext_param_promoted_not_compatible_with_prototype) << Warnings[Warn].PromotedType << Warnings[Warn].OldParm->getType(); if (Warnings[Warn].OldParm->getLocation().isValid()) Diag(Warnings[Warn].OldParm->getLocation(), diag::note_previous_declaration); } if (MergeTypeWithOld) New->setType(Context.getFunctionType(MergedReturn, ArgTypes, OldProto->getExtProtoInfo())); return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld); } // Fall through to diagnose conflicting types. } // A function that has already been declared has been redeclared or // defined with a different type; show an appropriate diagnostic. // If the previous declaration was an implicitly-generated builtin // declaration, then at the very least we should use a specialized note. unsigned BuiltinID; if (Old->isImplicit() && (BuiltinID = Old->getBuiltinID())) { // If it's actually a library-defined builtin function like 'malloc' // or 'printf', just warn about the incompatible redeclaration. if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) { Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New; Diag(OldLocation, diag::note_previous_builtin_declaration) << Old << Old->getType(); // If this is a global redeclaration, just forget hereafter // about the "builtin-ness" of the function. // // Doing this for local extern declarations is problematic. If // the builtin declaration remains visible, a second invalid // local declaration will produce a hard error; if it doesn't // remain visible, a single bogus local redeclaration (which is // actually only a warning) could break all the downstream code. if (!New->getLexicalDeclContext()->isFunctionOrMethod()) New->getIdentifier()->revertBuiltin(); return false; } PrevDiag = diag::note_previous_builtin_declaration; } Diag(New->getLocation(), diag::err_conflicting_types) << New->getDeclName(); Diag(OldLocation, PrevDiag) << Old << Old->getType(); return true; } /// \brief Completes the merge of two function declarations that are /// known to be compatible. /// /// This routine handles the merging of attributes and other /// properties of function declarations from the old declaration to /// the new declaration, once we know that New is in fact a /// redeclaration of Old. /// /// \returns false bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, Scope *S, bool MergeTypeWithOld) { // Merge the attributes mergeDeclAttributes(New, Old); // Merge "pure" flag. if (Old->isPure()) New->setPure(); // Merge "used" flag. if (Old->getMostRecentDecl()->isUsed(false)) New->setIsUsed(); // Merge attributes from the parameters. These can mismatch with K&R // declarations. if (New->getNumParams() == Old->getNumParams()) for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) { ParmVarDecl *NewParam = New->getParamDecl(i); ParmVarDecl *OldParam = Old->getParamDecl(i); mergeParamDeclAttributes(NewParam, OldParam, *this); mergeParamDeclTypes(NewParam, OldParam, *this); } if (getLangOpts().CPlusPlus) return MergeCXXFunctionDecl(New, Old, S); // Merge the function types so the we get the composite types for the return // and argument types. Per C11 6.2.7/4, only update the type if the old decl // was visible. QualType Merged = Context.mergeTypes(Old->getType(), New->getType()); if (!Merged.isNull() && MergeTypeWithOld) New->setType(Merged); return false; } void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, ObjCMethodDecl *oldMethod) { // Merge the attributes, including deprecated/unavailable AvailabilityMergeKind MergeKind = isa(oldMethod->getDeclContext()) ? AMK_ProtocolImplementation : isa(newMethod->getDeclContext()) ? AMK_Redeclaration : AMK_Override; mergeDeclAttributes(newMethod, oldMethod, MergeKind); // Merge attributes from the parameters. ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(), oe = oldMethod->param_end(); for (ObjCMethodDecl::param_iterator ni = newMethod->param_begin(), ne = newMethod->param_end(); ni != ne && oi != oe; ++ni, ++oi) mergeParamDeclAttributes(*ni, *oi, *this); CheckObjCMethodOverride(newMethod, oldMethod); } static void diagnoseVarDeclTypeMismatch(Sema &S, VarDecl *New, VarDecl* Old) { assert(!S.Context.hasSameType(New->getType(), Old->getType())); S.Diag(New->getLocation(), New->isThisDeclarationADefinition() ? diag::err_redefinition_different_type : diag::err_redeclaration_different_type) << New->getDeclName() << New->getType() << Old->getType(); diag::kind PrevDiag; SourceLocation OldLocation; std::tie(PrevDiag, OldLocation) = getNoteDiagForInvalidRedeclaration(Old, New); S.Diag(OldLocation, PrevDiag); New->setInvalidDecl(); } /// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and /// scope as a previous declaration 'Old'. Figure out how to merge their types, /// emitting diagnostics as appropriate. /// /// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back /// to here in AddInitializerToDecl. We can't check them before the initializer /// is attached. void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld) { if (New->isInvalidDecl() || Old->isInvalidDecl()) return; QualType MergedT; if (getLangOpts().CPlusPlus) { if (New->getType()->isUndeducedType()) { // We don't know what the new type is until the initializer is attached. return; } else if (Context.hasSameType(New->getType(), Old->getType())) { // These could still be something that needs exception specs checked. return MergeVarDeclExceptionSpecs(New, Old); } // C++ [basic.link]p10: // [...] the types specified by all declarations referring to a given // object or function shall be identical, except that declarations for an // array object can specify array types that differ by the presence or // absence of a major array bound (8.3.4). else if (Old->getType()->isArrayType() && New->getType()->isArrayType()) { const ArrayType *OldArray = Context.getAsArrayType(Old->getType()); const ArrayType *NewArray = Context.getAsArrayType(New->getType()); // We are merging a variable declaration New into Old. If it has an array // bound, and that bound differs from Old's bound, we should diagnose the // mismatch. if (!NewArray->isIncompleteArrayType() && !NewArray->isDependentType()) { for (VarDecl *PrevVD = Old->getMostRecentDecl(); PrevVD; PrevVD = PrevVD->getPreviousDecl()) { const ArrayType *PrevVDTy = Context.getAsArrayType(PrevVD->getType()); if (PrevVDTy->isIncompleteArrayType() || PrevVDTy->isDependentType()) continue; if (!Context.hasSameType(NewArray, PrevVDTy)) return diagnoseVarDeclTypeMismatch(*this, New, PrevVD); } } if (OldArray->isIncompleteArrayType() && NewArray->isArrayType()) { if (Context.hasSameType(OldArray->getElementType(), NewArray->getElementType())) MergedT = New->getType(); } // FIXME: Check visibility. New is hidden but has a complete type. If New // has no array bound, it should not inherit one from Old, if Old is not // visible. else if (OldArray->isArrayType() && NewArray->isIncompleteArrayType()) { if (Context.hasSameType(OldArray->getElementType(), NewArray->getElementType())) MergedT = Old->getType(); } } else if (New->getType()->isObjCObjectPointerType() && Old->getType()->isObjCObjectPointerType()) { MergedT = Context.mergeObjCGCQualifiers(New->getType(), Old->getType()); } } else { // C 6.2.7p2: // All declarations that refer to the same object or function shall have // compatible type. MergedT = Context.mergeTypes(New->getType(), Old->getType()); } if (MergedT.isNull()) { // It's OK if we couldn't merge types if either type is dependent, for a // block-scope variable. In other cases (static data members of class // templates, variable templates, ...), we require the types to be // equivalent. // FIXME: The C++ standard doesn't say anything about this. if ((New->getType()->isDependentType() || Old->getType()->isDependentType()) && New->isLocalVarDecl()) { // If the old type was dependent, we can't merge with it, so the new type // becomes dependent for now. We'll reproduce the original type when we // instantiate the TypeSourceInfo for the variable. if (!New->getType()->isDependentType() && MergeTypeWithOld) New->setType(Context.DependentTy); return; } return diagnoseVarDeclTypeMismatch(*this, New, Old); } // Don't actually update the type on the new declaration if the old // declaration was an extern declaration in a different scope. if (MergeTypeWithOld) New->setType(MergedT); } static bool mergeTypeWithPrevious(Sema &S, VarDecl *NewVD, VarDecl *OldVD, LookupResult &Previous) { // C11 6.2.7p4: // For an identifier with internal or external linkage declared // in a scope in which a prior declaration of that identifier is // visible, if the prior declaration specifies internal or // external linkage, the type of the identifier at the later // declaration becomes the composite type. // // If the variable isn't visible, we do not merge with its type. if (Previous.isShadowed()) return false; if (S.getLangOpts().CPlusPlus) { // C++11 [dcl.array]p3: // If there is a preceding declaration of the entity in the same // scope in which the bound was specified, an omitted array bound // is taken to be the same as in that earlier declaration. return NewVD->isPreviousDeclInSameBlockScope() || (!OldVD->getLexicalDeclContext()->isFunctionOrMethod() && !NewVD->getLexicalDeclContext()->isFunctionOrMethod()); } else { // If the old declaration was function-local, don't merge with its // type unless we're in the same function. return !OldVD->getLexicalDeclContext()->isFunctionOrMethod() || OldVD->getLexicalDeclContext() == NewVD->getLexicalDeclContext(); } } /// MergeVarDecl - We just parsed a variable 'New' which has the same name /// and scope as a previous declaration 'Old'. Figure out how to resolve this /// situation, merging decls or emitting diagnostics as appropriate. /// /// Tentative definition rules (C99 6.9.2p2) are checked by /// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative /// definitions here, since the initializer hasn't been attached. /// void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { // If the new decl is already invalid, don't do any other checking. if (New->isInvalidDecl()) return; if (!shouldLinkPossiblyHiddenDecl(Previous, New)) return; VarTemplateDecl *NewTemplate = New->getDescribedVarTemplate(); // Verify the old decl was also a variable or variable template. VarDecl *Old = nullptr; VarTemplateDecl *OldTemplate = nullptr; if (Previous.isSingleResult()) { if (NewTemplate) { OldTemplate = dyn_cast(Previous.getFoundDecl()); Old = OldTemplate ? OldTemplate->getTemplatedDecl() : nullptr; if (auto *Shadow = dyn_cast(Previous.getRepresentativeDecl())) if (checkUsingShadowRedecl(*this, Shadow, NewTemplate)) return New->setInvalidDecl(); } else { Old = dyn_cast(Previous.getFoundDecl()); if (auto *Shadow = dyn_cast(Previous.getRepresentativeDecl())) if (checkUsingShadowRedecl(*this, Shadow, New)) return New->setInvalidDecl(); } } if (!Old) { Diag(New->getLocation(), diag::err_redefinition_different_kind) << New->getDeclName(); notePreviousDefinition(Previous.getRepresentativeDecl(), New->getLocation()); return New->setInvalidDecl(); } // Ensure the template parameters are compatible. if (NewTemplate && !TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), OldTemplate->getTemplateParameters(), /*Complain=*/true, TPL_TemplateMatch)) return New->setInvalidDecl(); // C++ [class.mem]p1: // A member shall not be declared twice in the member-specification [...] // // Here, we need only consider static data members. if (Old->isStaticDataMember() && !New->isOutOfLine()) { Diag(New->getLocation(), diag::err_duplicate_member) << New->getIdentifier(); Diag(Old->getLocation(), diag::note_previous_declaration); New->setInvalidDecl(); } mergeDeclAttributes(New, Old); // Warn if an already-declared variable is made a weak_import in a subsequent // declaration if (New->hasAttr() && Old->getStorageClass() == SC_None && !Old->hasAttr()) { Diag(New->getLocation(), diag::warn_weak_import) << New->getDeclName(); notePreviousDefinition(Old, New->getLocation()); // Remove weak_import attribute on new declaration. New->dropAttr(); } if (New->hasAttr() && !Old->hasAttr()) { Diag(New->getLocation(), diag::err_internal_linkage_redeclaration) << New->getDeclName(); notePreviousDefinition(Old, New->getLocation()); New->dropAttr(); } // Merge the types. VarDecl *MostRecent = Old->getMostRecentDecl(); if (MostRecent != Old) { MergeVarDeclTypes(New, MostRecent, mergeTypeWithPrevious(*this, New, MostRecent, Previous)); if (New->isInvalidDecl()) return; } MergeVarDeclTypes(New, Old, mergeTypeWithPrevious(*this, New, Old, Previous)); if (New->isInvalidDecl()) return; diag::kind PrevDiag; SourceLocation OldLocation; std::tie(PrevDiag, OldLocation) = getNoteDiagForInvalidRedeclaration(Old, New); // [dcl.stc]p8: Check if we have a non-static decl followed by a static. if (New->getStorageClass() == SC_Static && !New->isStaticDataMember() && Old->hasExternalFormalLinkage()) { if (getLangOpts().MicrosoftExt) { Diag(New->getLocation(), diag::ext_static_non_static) << New->getDeclName(); Diag(OldLocation, PrevDiag); } else { Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName(); Diag(OldLocation, PrevDiag); return New->setInvalidDecl(); } } // C99 6.2.2p4: // For an identifier declared with the storage-class specifier // extern in a scope in which a prior declaration of that // identifier is visible,23) if the prior declaration specifies // internal or external linkage, the linkage of the identifier at // the later declaration is the same as the linkage specified at // the prior declaration. If no prior declaration is visible, or // if the prior declaration specifies no linkage, then the // identifier has external linkage. if (New->hasExternalStorage() && Old->hasLinkage()) /* Okay */; else if (New->getCanonicalDecl()->getStorageClass() != SC_Static && !New->isStaticDataMember() && Old->getCanonicalDecl()->getStorageClass() == SC_Static) { Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName(); Diag(OldLocation, PrevDiag); return New->setInvalidDecl(); } // Check if extern is followed by non-extern and vice-versa. if (New->hasExternalStorage() && !Old->hasLinkage() && Old->isLocalVarDeclOrParm()) { Diag(New->getLocation(), diag::err_extern_non_extern) << New->getDeclName(); Diag(OldLocation, PrevDiag); return New->setInvalidDecl(); } if (Old->hasLinkage() && New->isLocalVarDeclOrParm() && !New->hasExternalStorage()) { Diag(New->getLocation(), diag::err_non_extern_extern) << New->getDeclName(); Diag(OldLocation, PrevDiag); return New->setInvalidDecl(); } // Variables with external linkage are analyzed in FinalizeDeclaratorGroup. // FIXME: The test for external storage here seems wrong? We still // need to check for mismatches. if (!New->hasExternalStorage() && !New->isFileVarDecl() && // Don't complain about out-of-line definitions of static members. !(Old->getLexicalDeclContext()->isRecord() && !New->getLexicalDeclContext()->isRecord())) { Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName(); Diag(OldLocation, PrevDiag); return New->setInvalidDecl(); } if (New->isInline() && !Old->getMostRecentDecl()->isInline()) { if (VarDecl *Def = Old->getDefinition()) { // C++1z [dcl.fcn.spec]p4: // If the definition of a variable appears in a translation unit before // its first declaration as inline, the program is ill-formed. Diag(New->getLocation(), diag::err_inline_decl_follows_def) << New; Diag(Def->getLocation(), diag::note_previous_definition); } } // If this redeclaration makes the function inline, we may need to add it to // UndefinedButUsed. if (!Old->isInline() && New->isInline() && Old->isUsed(false) && !Old->getDefinition() && !New->isThisDeclarationADefinition()) UndefinedButUsed.insert(std::make_pair(Old->getCanonicalDecl(), SourceLocation())); if (New->getTLSKind() != Old->getTLSKind()) { if (!Old->getTLSKind()) { Diag(New->getLocation(), diag::err_thread_non_thread) << New->getDeclName(); Diag(OldLocation, PrevDiag); } else if (!New->getTLSKind()) { Diag(New->getLocation(), diag::err_non_thread_thread) << New->getDeclName(); Diag(OldLocation, PrevDiag); } else { // Do not allow redeclaration to change the variable between requiring // static and dynamic initialization. // FIXME: GCC allows this, but uses the TLS keyword on the first // declaration to determine the kind. Do we need to be compatible here? Diag(New->getLocation(), diag::err_thread_thread_different_kind) << New->getDeclName() << (New->getTLSKind() == VarDecl::TLS_Dynamic); Diag(OldLocation, PrevDiag); } } // C++ doesn't have tentative definitions, so go right ahead and check here. if (getLangOpts().CPlusPlus && New->isThisDeclarationADefinition() == VarDecl::Definition) { if (Old->isStaticDataMember() && Old->getCanonicalDecl()->isInline() && Old->getCanonicalDecl()->isConstexpr()) { // This definition won't be a definition any more once it's been merged. Diag(New->getLocation(), diag::warn_deprecated_redundant_constexpr_static_def); } else if (VarDecl *Def = Old->getDefinition()) { if (checkVarDeclRedefinition(Def, New)) return; } } if (haveIncompatibleLanguageLinkages(Old, New)) { Diag(New->getLocation(), diag::err_different_language_linkage) << New; Diag(OldLocation, PrevDiag); New->setInvalidDecl(); return; } // Merge "used" flag. if (Old->getMostRecentDecl()->isUsed(false)) New->setIsUsed(); // Keep a chain of previous declarations. New->setPreviousDecl(Old); if (NewTemplate) NewTemplate->setPreviousDecl(OldTemplate); // Inherit access appropriately. New->setAccess(Old->getAccess()); if (NewTemplate) NewTemplate->setAccess(New->getAccess()); if (Old->isInline()) New->setImplicitlyInline(); } void Sema::notePreviousDefinition(const NamedDecl *Old, SourceLocation New) { SourceManager &SrcMgr = getSourceManager(); auto FNewDecLoc = SrcMgr.getDecomposedLoc(New); auto FOldDecLoc = SrcMgr.getDecomposedLoc(Old->getLocation()); auto *FNew = SrcMgr.getFileEntryForID(FNewDecLoc.first); auto *FOld = SrcMgr.getFileEntryForID(FOldDecLoc.first); auto &HSI = PP.getHeaderSearchInfo(); StringRef HdrFilename = SrcMgr.getFilename(SrcMgr.getSpellingLoc(Old->getLocation())); auto noteFromModuleOrInclude = [&](Module *Mod, SourceLocation IncLoc) -> bool { // Redefinition errors with modules are common with non modular mapped // headers, example: a non-modular header H in module A that also gets // included directly in a TU. Pointing twice to the same header/definition // is confusing, try to get better diagnostics when modules is on. if (IncLoc.isValid()) { if (Mod) { Diag(IncLoc, diag::note_redefinition_modules_same_file) << HdrFilename.str() << Mod->getFullModuleName(); if (!Mod->DefinitionLoc.isInvalid()) Diag(Mod->DefinitionLoc, diag::note_defined_here) << Mod->getFullModuleName(); } else { Diag(IncLoc, diag::note_redefinition_include_same_file) << HdrFilename.str(); } return true; } return false; }; // Is it the same file and same offset? Provide more information on why // this leads to a redefinition error. bool EmittedDiag = false; if (FNew == FOld && FNewDecLoc.second == FOldDecLoc.second) { SourceLocation OldIncLoc = SrcMgr.getIncludeLoc(FOldDecLoc.first); SourceLocation NewIncLoc = SrcMgr.getIncludeLoc(FNewDecLoc.first); EmittedDiag = noteFromModuleOrInclude(Old->getOwningModule(), OldIncLoc); EmittedDiag |= noteFromModuleOrInclude(getCurrentModule(), NewIncLoc); // If the header has no guards, emit a note suggesting one. if (FOld && !HSI.isFileMultipleIncludeGuarded(FOld)) Diag(Old->getLocation(), diag::note_use_ifdef_guards); if (EmittedDiag) return; } // Redefinition coming from different files or couldn't do better above. Diag(Old->getLocation(), diag::note_previous_definition); } /// We've just determined that \p Old and \p New both appear to be definitions /// of the same variable. Either diagnose or fix the problem. bool Sema::checkVarDeclRedefinition(VarDecl *Old, VarDecl *New) { if (!hasVisibleDefinition(Old) && (New->getFormalLinkage() == InternalLinkage || New->isInline() || New->getDescribedVarTemplate() || New->getNumTemplateParameterLists() || New->getDeclContext()->isDependentContext())) { // The previous definition is hidden, and multiple definitions are // permitted (in separate TUs). Demote this to a declaration. New->demoteThisDefinitionToDeclaration(); // Make the canonical definition visible. if (auto *OldTD = Old->getDescribedVarTemplate()) makeMergedDefinitionVisible(OldTD); makeMergedDefinitionVisible(Old); return false; } else { Diag(New->getLocation(), diag::err_redefinition) << New; notePreviousDefinition(Old, New->getLocation()); New->setInvalidDecl(); return true; } } /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with /// no declarator (e.g. "struct foo;") is parsed. Decl * Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, RecordDecl *&AnonRecord) { return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg(), false, AnonRecord); } // The MS ABI changed between VS2013 and VS2015 with regard to numbers used to // disambiguate entities defined in different scopes. // While the VS2015 ABI fixes potential miscompiles, it is also breaks // compatibility. // We will pick our mangling number depending on which version of MSVC is being // targeted. static unsigned getMSManglingNumber(const LangOptions &LO, Scope *S) { return LO.isCompatibleWithMSVC(LangOptions::MSVC2015) ? S->getMSCurManglingNumber() : S->getMSLastManglingNumber(); } void Sema::handleTagNumbering(const TagDecl *Tag, Scope *TagScope) { if (!Context.getLangOpts().CPlusPlus) return; if (isa(Tag->getParent())) { // If this tag is the direct child of a class, number it if // it is anonymous. if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl()) return; MangleNumberingContext &MCtx = Context.getManglingNumberContext(Tag->getParent()); Context.setManglingNumber( Tag, MCtx.getManglingNumber( Tag, getMSManglingNumber(getLangOpts(), TagScope))); return; } // If this tag isn't a direct child of a class, number it if it is local. Decl *ManglingContextDecl; if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext( Tag->getDeclContext(), ManglingContextDecl)) { Context.setManglingNumber( Tag, MCtx->getManglingNumber( Tag, getMSManglingNumber(getLangOpts(), TagScope))); } } void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec, TypedefNameDecl *NewTD) { if (TagFromDeclSpec->isInvalidDecl()) return; // Do nothing if the tag already has a name for linkage purposes. if (TagFromDeclSpec->hasNameForLinkage()) return; // A well-formed anonymous tag must always be a TUK_Definition. assert(TagFromDeclSpec->isThisDeclarationADefinition()); // The type must match the tag exactly; no qualifiers allowed. if (!Context.hasSameType(NewTD->getUnderlyingType(), Context.getTagDeclType(TagFromDeclSpec))) { if (getLangOpts().CPlusPlus) Context.addTypedefNameForUnnamedTagDecl(TagFromDeclSpec, NewTD); return; } // If we've already computed linkage for the anonymous tag, then // adding a typedef name for the anonymous decl can change that // linkage, which might be a serious problem. Diagnose this as // unsupported and ignore the typedef name. TODO: we should // pursue this as a language defect and establish a formal rule // for how to handle it. if (TagFromDeclSpec->hasLinkageBeenComputed()) { Diag(NewTD->getLocation(), diag::err_typedef_changes_linkage); SourceLocation tagLoc = TagFromDeclSpec->getInnerLocStart(); tagLoc = getLocForEndOfToken(tagLoc); llvm::SmallString<40> textToInsert; textToInsert += ' '; textToInsert += NewTD->getIdentifier()->getName(); Diag(tagLoc, diag::note_typedef_changes_linkage) << FixItHint::CreateInsertion(tagLoc, textToInsert); return; } // Otherwise, set this is the anon-decl typedef for the tag. TagFromDeclSpec->setTypedefNameForAnonDecl(NewTD); } static unsigned GetDiagnosticTypeSpecifierID(DeclSpec::TST T) { switch (T) { case DeclSpec::TST_class: return 0; case DeclSpec::TST_struct: return 1; case DeclSpec::TST_interface: return 2; case DeclSpec::TST_union: return 3; case DeclSpec::TST_enum: return 4; default: llvm_unreachable("unexpected type specifier"); } } /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with /// no declarator (e.g. "struct foo;") is parsed. It also accepts template /// parameters to cope with template friend declarations. Decl * Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, MultiTemplateParamsArg TemplateParams, bool IsExplicitInstantiation, RecordDecl *&AnonRecord) { Decl *TagD = nullptr; TagDecl *Tag = nullptr; if (DS.getTypeSpecType() == DeclSpec::TST_class || DS.getTypeSpecType() == DeclSpec::TST_struct || DS.getTypeSpecType() == DeclSpec::TST_interface || DS.getTypeSpecType() == DeclSpec::TST_union || DS.getTypeSpecType() == DeclSpec::TST_enum) { TagD = DS.getRepAsDecl(); if (!TagD) // We probably had an error return nullptr; // Note that the above type specs guarantee that the // type rep is a Decl, whereas in many of the others // it's a Type. if (isa(TagD)) Tag = cast(TagD); else if (ClassTemplateDecl *CTD = dyn_cast(TagD)) Tag = CTD->getTemplatedDecl(); } if (Tag) { handleTagNumbering(Tag, S); Tag->setFreeStanding(); if (Tag->isInvalidDecl()) return Tag; } if (unsigned TypeQuals = DS.getTypeQualifiers()) { // Enforce C99 6.7.3p2: "Types other than pointer types derived from object // or incomplete types shall not be restrict-qualified." if (TypeQuals & DeclSpec::TQ_restrict) Diag(DS.getRestrictSpecLoc(), diag::err_typecheck_invalid_restrict_not_pointer_noarg) << DS.getSourceRange(); } if (DS.isInlineSpecified()) Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function) << getLangOpts().CPlusPlus1z; if (DS.isConstexprSpecified()) { // C++0x [dcl.constexpr]p1: constexpr can only be applied to declarations // and definitions of functions and variables. if (Tag) Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag) << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()); else Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_no_declarators); // Don't emit warnings after this error. return TagD; } if (DS.isConceptSpecified()) { // C++ Concepts TS [dcl.spec.concept]p1: A concept definition refers to // either a function concept and its definition or a variable concept and // its initializer. Diag(DS.getConceptSpecLoc(), diag::err_concept_wrong_decl_kind); return TagD; } DiagnoseFunctionSpecifiers(DS); if (DS.isFriendSpecified()) { // If we're dealing with a decl but not a TagDecl, assume that // whatever routines created it handled the friendship aspect. if (TagD && !Tag) return nullptr; return ActOnFriendTypeDecl(S, DS, TemplateParams); } const CXXScopeSpec &SS = DS.getTypeSpecScope(); bool IsExplicitSpecialization = !TemplateParams.empty() && TemplateParams.back()->size() == 0; if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() && !IsExplicitInstantiation && !IsExplicitSpecialization && !isa(Tag)) { // Per C++ [dcl.type.elab]p1, a class declaration cannot have a // nested-name-specifier unless it is an explicit instantiation // or an explicit specialization. // // FIXME: We allow class template partial specializations here too, per the // obvious intent of DR1819. // // Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either. Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier) << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) << SS.getRange(); return nullptr; } // Track whether this decl-specifier declares anything. bool DeclaresAnything = true; // Handle anonymous struct definitions. if (RecordDecl *Record = dyn_cast_or_null(Tag)) { if (!Record->getDeclName() && Record->isCompleteDefinition() && DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { if (getLangOpts().CPlusPlus || Record->getDeclContext()->isRecord()) { // If CurContext is a DeclContext that can contain statements, // RecursiveASTVisitor won't visit the decls that // BuildAnonymousStructOrUnion() will put into CurContext. // Also store them here so that they can be part of the // DeclStmt that gets created in this case. // FIXME: Also return the IndirectFieldDecls created by // BuildAnonymousStructOr union, for the same reason? if (CurContext->isFunctionOrMethod()) AnonRecord = Record; return BuildAnonymousStructOrUnion(S, DS, AS, Record, Context.getPrintingPolicy()); } DeclaresAnything = false; } } // C11 6.7.2.1p2: // A struct-declaration that does not declare an anonymous structure or // anonymous union shall contain a struct-declarator-list. // // This rule also existed in C89 and C99; the grammar for struct-declaration // did not permit a struct-declaration without a struct-declarator-list. if (!getLangOpts().CPlusPlus && CurContext->isRecord() && DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) { // Check for Microsoft C extension: anonymous struct/union member. // Handle 2 kinds of anonymous struct/union: // struct STRUCT; // union UNION; // and // STRUCT_TYPE; <- where STRUCT_TYPE is a typedef struct. // UNION_TYPE; <- where UNION_TYPE is a typedef union. if ((Tag && Tag->getDeclName()) || DS.getTypeSpecType() == DeclSpec::TST_typename) { RecordDecl *Record = nullptr; if (Tag) Record = dyn_cast(Tag); else if (const RecordType *RT = DS.getRepAsType().get()->getAsStructureType()) Record = RT->getDecl(); else if (const RecordType *UT = DS.getRepAsType().get()->getAsUnionType()) Record = UT->getDecl(); if (Record && getLangOpts().MicrosoftExt) { Diag(DS.getLocStart(), diag::ext_ms_anonymous_record) << Record->isUnion() << DS.getSourceRange(); return BuildMicrosoftCAnonymousStruct(S, DS, Record); } DeclaresAnything = false; } } // Skip all the checks below if we have a type error. if (DS.getTypeSpecType() == DeclSpec::TST_error || (TagD && TagD->isInvalidDecl())) return TagD; if (getLangOpts().CPlusPlus && DS.getStorageClassSpec() != DeclSpec::SCS_typedef) if (EnumDecl *Enum = dyn_cast_or_null(Tag)) if (Enum->enumerator_begin() == Enum->enumerator_end() && !Enum->getIdentifier() && !Enum->isInvalidDecl()) DeclaresAnything = false; if (!DS.isMissingDeclaratorOk()) { // Customize diagnostic for a typedef missing a name. if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) Diag(DS.getLocStart(), diag::ext_typedef_without_a_name) << DS.getSourceRange(); else DeclaresAnything = false; } if (DS.isModulePrivateSpecified() && Tag && Tag->getDeclContext()->isFunctionOrMethod()) Diag(DS.getModulePrivateSpecLoc(), diag::err_module_private_local_class) << Tag->getTagKind() << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc()); ActOnDocumentableDecl(TagD); // C 6.7/2: // A declaration [...] shall declare at least a declarator [...], a tag, // or the members of an enumeration. // C++ [dcl.dcl]p3: // [If there are no declarators], and except for the declaration of an // unnamed bit-field, the decl-specifier-seq shall introduce one or more // names into the program, or shall redeclare a name introduced by a // previous declaration. if (!DeclaresAnything) { // In C, we allow this as a (popular) extension / bug. Don't bother // producing further diagnostics for redundant qualifiers after this. Diag(DS.getLocStart(), diag::ext_no_declarators) << DS.getSourceRange(); return TagD; } // C++ [dcl.stc]p1: // If a storage-class-specifier appears in a decl-specifier-seq, [...] the // init-declarator-list of the declaration shall not be empty. // C++ [dcl.fct.spec]p1: // If a cv-qualifier appears in a decl-specifier-seq, the // init-declarator-list of the declaration shall not be empty. // // Spurious qualifiers here appear to be valid in C. unsigned DiagID = diag::warn_standalone_specifier; if (getLangOpts().CPlusPlus) DiagID = diag::ext_standalone_specifier; // Note that a linkage-specification sets a storage class, but // 'extern "C" struct foo;' is actually valid and not theoretically // useless. if (DeclSpec::SCS SCS = DS.getStorageClassSpec()) { if (SCS == DeclSpec::SCS_mutable) // Since mutable is not a viable storage class specifier in C, there is // no reason to treat it as an extension. Instead, diagnose as an error. Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_nonmember); else if (!DS.isExternInLinkageSpec() && SCS != DeclSpec::SCS_typedef) Diag(DS.getStorageClassSpecLoc(), DiagID) << DeclSpec::getSpecifierName(SCS); } if (DeclSpec::TSCS TSCS = DS.getThreadStorageClassSpec()) Diag(DS.getThreadStorageClassSpecLoc(), DiagID) << DeclSpec::getSpecifierName(TSCS); if (DS.getTypeQualifiers()) { if (DS.getTypeQualifiers() & DeclSpec::TQ_const) Diag(DS.getConstSpecLoc(), DiagID) << "const"; if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) Diag(DS.getConstSpecLoc(), DiagID) << "volatile"; // Restrict is covered above. if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) Diag(DS.getAtomicSpecLoc(), DiagID) << "_Atomic"; if (DS.getTypeQualifiers() & DeclSpec::TQ_unaligned) Diag(DS.getUnalignedSpecLoc(), DiagID) << "__unaligned"; } // Warn about ignored type attributes, for example: // __attribute__((aligned)) struct A; // Attributes should be placed after tag to apply to type declaration. if (!DS.getAttributes().empty()) { DeclSpec::TST TypeSpecType = DS.getTypeSpecType(); if (TypeSpecType == DeclSpec::TST_class || TypeSpecType == DeclSpec::TST_struct || TypeSpecType == DeclSpec::TST_interface || TypeSpecType == DeclSpec::TST_union || TypeSpecType == DeclSpec::TST_enum) { for (AttributeList* attrs = DS.getAttributes().getList(); attrs; attrs = attrs->getNext()) Diag(attrs->getLoc(), diag::warn_declspec_attribute_ignored) << attrs->getName() << GetDiagnosticTypeSpecifierID(TypeSpecType); } } return TagD; } /// We are trying to inject an anonymous member into the given scope; /// check if there's an existing declaration that can't be overloaded. /// /// \return true if this is a forbidden redeclaration static bool CheckAnonMemberRedeclaration(Sema &SemaRef, Scope *S, DeclContext *Owner, DeclarationName Name, SourceLocation NameLoc, bool IsUnion) { LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName, Sema::ForRedeclaration); if (!SemaRef.LookupName(R, S)) return false; // Pick a representative declaration. NamedDecl *PrevDecl = R.getRepresentativeDecl()->getUnderlyingDecl(); assert(PrevDecl && "Expected a non-null Decl"); if (!SemaRef.isDeclInScope(PrevDecl, Owner, S)) return false; SemaRef.Diag(NameLoc, diag::err_anonymous_record_member_redecl) << IsUnion << Name; SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration); return true; } /// InjectAnonymousStructOrUnionMembers - Inject the members of the /// anonymous struct or union AnonRecord into the owning context Owner /// and scope S. This routine will be invoked just after we realize /// that an unnamed union or struct is actually an anonymous union or /// struct, e.g., /// /// @code /// union { /// int i; /// float f; /// }; // InjectAnonymousStructOrUnionMembers called here to inject i and /// // f into the surrounding scope.x /// @endcode /// /// This routine is recursive, injecting the names of nested anonymous /// structs/unions into the owning context and scope as well. static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, DeclContext *Owner, RecordDecl *AnonRecord, AccessSpecifier AS, SmallVectorImpl &Chaining) { bool Invalid = false; // Look every FieldDecl and IndirectFieldDecl with a name. for (auto *D : AnonRecord->decls()) { if ((isa(D) || isa(D)) && cast(D)->getDeclName()) { ValueDecl *VD = cast(D); if (CheckAnonMemberRedeclaration(SemaRef, S, Owner, VD->getDeclName(), VD->getLocation(), AnonRecord->isUnion())) { // C++ [class.union]p2: // The names of the members of an anonymous union shall be // distinct from the names of any other entity in the // scope in which the anonymous union is declared. Invalid = true; } else { // C++ [class.union]p2: // For the purpose of name lookup, after the anonymous union // definition, the members of the anonymous union are // considered to have been defined in the scope in which the // anonymous union is declared. unsigned OldChainingSize = Chaining.size(); if (IndirectFieldDecl *IF = dyn_cast(VD)) Chaining.append(IF->chain_begin(), IF->chain_end()); else Chaining.push_back(VD); assert(Chaining.size() >= 2); NamedDecl **NamedChain = new (SemaRef.Context)NamedDecl*[Chaining.size()]; for (unsigned i = 0; i < Chaining.size(); i++) NamedChain[i] = Chaining[i]; IndirectFieldDecl *IndirectField = IndirectFieldDecl::Create( SemaRef.Context, Owner, VD->getLocation(), VD->getIdentifier(), VD->getType(), {NamedChain, Chaining.size()}); for (const auto *Attr : VD->attrs()) IndirectField->addAttr(Attr->clone(SemaRef.Context)); IndirectField->setAccess(AS); IndirectField->setImplicit(); SemaRef.PushOnScopeChains(IndirectField, S); // That includes picking up the appropriate access specifier. if (AS != AS_none) IndirectField->setAccess(AS); Chaining.resize(OldChainingSize); } } } return Invalid; } /// StorageClassSpecToVarDeclStorageClass - Maps a DeclSpec::SCS to /// a VarDecl::StorageClass. Any error reporting is up to the caller: /// illegal input values are mapped to SC_None. static StorageClass StorageClassSpecToVarDeclStorageClass(const DeclSpec &DS) { DeclSpec::SCS StorageClassSpec = DS.getStorageClassSpec(); assert(StorageClassSpec != DeclSpec::SCS_typedef && "Parser allowed 'typedef' as storage class VarDecl."); switch (StorageClassSpec) { case DeclSpec::SCS_unspecified: return SC_None; case DeclSpec::SCS_extern: if (DS.isExternInLinkageSpec()) return SC_None; return SC_Extern; case DeclSpec::SCS_static: return SC_Static; case DeclSpec::SCS_auto: return SC_Auto; case DeclSpec::SCS_register: return SC_Register; case DeclSpec::SCS_private_extern: return SC_PrivateExtern; // Illegal SCSs map to None: error reporting is up to the caller. case DeclSpec::SCS_mutable: // Fall through. case DeclSpec::SCS_typedef: return SC_None; } llvm_unreachable("unknown storage class specifier"); } static SourceLocation findDefaultInitializer(const CXXRecordDecl *Record) { assert(Record->hasInClassInitializer()); for (const auto *I : Record->decls()) { const auto *FD = dyn_cast(I); if (const auto *IFD = dyn_cast(I)) FD = IFD->getAnonField(); if (FD && FD->hasInClassInitializer()) return FD->getLocation(); } llvm_unreachable("couldn't find in-class initializer"); } static void checkDuplicateDefaultInit(Sema &S, CXXRecordDecl *Parent, SourceLocation DefaultInitLoc) { if (!Parent->isUnion() || !Parent->hasInClassInitializer()) return; S.Diag(DefaultInitLoc, diag::err_multiple_mem_union_initialization); S.Diag(findDefaultInitializer(Parent), diag::note_previous_initializer) << 0; } static void checkDuplicateDefaultInit(Sema &S, CXXRecordDecl *Parent, CXXRecordDecl *AnonUnion) { if (!Parent->isUnion() || !Parent->hasInClassInitializer()) return; checkDuplicateDefaultInit(S, Parent, findDefaultInitializer(AnonUnion)); } /// BuildAnonymousStructOrUnion - Handle the declaration of an /// anonymous structure or union. Anonymous unions are a C++ feature /// (C++ [class.union]) and a C11 feature; anonymous structures /// are a C11 feature and GNU C++ extension. Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, AccessSpecifier AS, RecordDecl *Record, const PrintingPolicy &Policy) { DeclContext *Owner = Record->getDeclContext(); // Diagnose whether this anonymous struct/union is an extension. if (Record->isUnion() && !getLangOpts().CPlusPlus && !getLangOpts().C11) Diag(Record->getLocation(), diag::ext_anonymous_union); else if (!Record->isUnion() && getLangOpts().CPlusPlus) Diag(Record->getLocation(), diag::ext_gnu_anonymous_struct); else if (!Record->isUnion() && !getLangOpts().C11) Diag(Record->getLocation(), diag::ext_c11_anonymous_struct); // C and C++ require different kinds of checks for anonymous // structs/unions. bool Invalid = false; if (getLangOpts().CPlusPlus) { const char *PrevSpec = nullptr; unsigned DiagID; if (Record->isUnion()) { // C++ [class.union]p6: // Anonymous unions declared in a named namespace or in the // global namespace shall be declared static. if (DS.getStorageClassSpec() != DeclSpec::SCS_static && (isa(Owner) || (isa(Owner) && cast(Owner)->getDeclName()))) { Diag(Record->getLocation(), diag::err_anonymous_union_not_static) << FixItHint::CreateInsertion(Record->getLocation(), "static "); // Recover by adding 'static'. DS.SetStorageClassSpec(*this, DeclSpec::SCS_static, SourceLocation(), PrevSpec, DiagID, Policy); } // C++ [class.union]p6: // A storage class is not allowed in a declaration of an // anonymous union in a class scope. else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified && isa(Owner)) { Diag(DS.getStorageClassSpecLoc(), diag::err_anonymous_union_with_storage_spec) << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); // Recover by removing the storage specifier. DS.SetStorageClassSpec(*this, DeclSpec::SCS_unspecified, SourceLocation(), PrevSpec, DiagID, Context.getPrintingPolicy()); } } // Ignore const/volatile/restrict qualifiers. if (DS.getTypeQualifiers()) { if (DS.getTypeQualifiers() & DeclSpec::TQ_const) Diag(DS.getConstSpecLoc(), diag::ext_anonymous_struct_union_qualified) << Record->isUnion() << "const" << FixItHint::CreateRemoval(DS.getConstSpecLoc()); if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) Diag(DS.getVolatileSpecLoc(), diag::ext_anonymous_struct_union_qualified) << Record->isUnion() << "volatile" << FixItHint::CreateRemoval(DS.getVolatileSpecLoc()); if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) Diag(DS.getRestrictSpecLoc(), diag::ext_anonymous_struct_union_qualified) << Record->isUnion() << "restrict" << FixItHint::CreateRemoval(DS.getRestrictSpecLoc()); if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) Diag(DS.getAtomicSpecLoc(), diag::ext_anonymous_struct_union_qualified) << Record->isUnion() << "_Atomic" << FixItHint::CreateRemoval(DS.getAtomicSpecLoc()); if (DS.getTypeQualifiers() & DeclSpec::TQ_unaligned) Diag(DS.getUnalignedSpecLoc(), diag::ext_anonymous_struct_union_qualified) << Record->isUnion() << "__unaligned" << FixItHint::CreateRemoval(DS.getUnalignedSpecLoc()); DS.ClearTypeQualifiers(); } // C++ [class.union]p2: // The member-specification of an anonymous union shall only // define non-static data members. [Note: nested types and // functions cannot be declared within an anonymous union. ] for (auto *Mem : Record->decls()) { if (auto *FD = dyn_cast(Mem)) { // C++ [class.union]p3: // An anonymous union shall not have private or protected // members (clause 11). assert(FD->getAccess() != AS_none); if (FD->getAccess() != AS_public) { Diag(FD->getLocation(), diag::err_anonymous_record_nonpublic_member) << Record->isUnion() << (FD->getAccess() == AS_protected); Invalid = true; } // C++ [class.union]p1 // An object of a class with a non-trivial constructor, a non-trivial // copy constructor, a non-trivial destructor, or a non-trivial copy // assignment operator cannot be a member of a union, nor can an // array of such objects. if (CheckNontrivialField(FD)) Invalid = true; } else if (Mem->isImplicit()) { // Any implicit members are fine. } else if (isa(Mem) && Mem->getDeclContext() != Record) { // This is a type that showed up in an // elaborated-type-specifier inside the anonymous struct or // union, but which actually declares a type outside of the // anonymous struct or union. It's okay. } else if (auto *MemRecord = dyn_cast(Mem)) { if (!MemRecord->isAnonymousStructOrUnion() && MemRecord->getDeclName()) { // Visual C++ allows type definition in anonymous struct or union. if (getLangOpts().MicrosoftExt) Diag(MemRecord->getLocation(), diag::ext_anonymous_record_with_type) << Record->isUnion(); else { // This is a nested type declaration. Diag(MemRecord->getLocation(), diag::err_anonymous_record_with_type) << Record->isUnion(); Invalid = true; } } else { // This is an anonymous type definition within another anonymous type. // This is a popular extension, provided by Plan9, MSVC and GCC, but // not part of standard C++. Diag(MemRecord->getLocation(), diag::ext_anonymous_record_with_anonymous_type) << Record->isUnion(); } } else if (isa(Mem)) { // Any access specifier is fine. } else if (isa(Mem)) { // In C++1z, static_assert declarations are also fine. } else { // We have something that isn't a non-static data // member. Complain about it. unsigned DK = diag::err_anonymous_record_bad_member; if (isa(Mem)) DK = diag::err_anonymous_record_with_type; else if (isa(Mem)) DK = diag::err_anonymous_record_with_function; else if (isa(Mem)) DK = diag::err_anonymous_record_with_static; // Visual C++ allows type definition in anonymous struct or union. if (getLangOpts().MicrosoftExt && DK == diag::err_anonymous_record_with_type) Diag(Mem->getLocation(), diag::ext_anonymous_record_with_type) << Record->isUnion(); else { Diag(Mem->getLocation(), DK) << Record->isUnion(); Invalid = true; } } } // C++11 [class.union]p8 (DR1460): // At most one variant member of a union may have a // brace-or-equal-initializer. if (cast(Record)->hasInClassInitializer() && Owner->isRecord()) checkDuplicateDefaultInit(*this, cast(Owner), cast(Record)); } if (!Record->isUnion() && !Owner->isRecord()) { Diag(Record->getLocation(), diag::err_anonymous_struct_not_member) << getLangOpts().CPlusPlus; Invalid = true; } // Mock up a declarator. Declarator Dc(DS, Declarator::MemberContext); TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S); assert(TInfo && "couldn't build declarator info for anonymous struct/union"); // Create a declaration for this anonymous struct/union. NamedDecl *Anon = nullptr; if (RecordDecl *OwningClass = dyn_cast(Owner)) { Anon = FieldDecl::Create(Context, OwningClass, DS.getLocStart(), Record->getLocation(), /*IdentifierInfo=*/nullptr, Context.getTypeDeclType(Record), TInfo, /*BitWidth=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); Anon->setAccess(AS); if (getLangOpts().CPlusPlus) FieldCollector->Add(cast(Anon)); } else { DeclSpec::SCS SCSpec = DS.getStorageClassSpec(); StorageClass SC = StorageClassSpecToVarDeclStorageClass(DS); if (SCSpec == DeclSpec::SCS_mutable) { // mutable can only appear on non-static class members, so it's always // an error here Diag(Record->getLocation(), diag::err_mutable_nonmember); Invalid = true; SC = SC_None; } Anon = VarDecl::Create(Context, Owner, DS.getLocStart(), Record->getLocation(), /*IdentifierInfo=*/nullptr, Context.getTypeDeclType(Record), TInfo, SC); // Default-initialize the implicit variable. This initialization will be // trivial in almost all cases, except if a union member has an in-class // initializer: // union { int n = 0; }; ActOnUninitializedDecl(Anon); } Anon->setImplicit(); // Mark this as an anonymous struct/union type. Record->setAnonymousStructOrUnion(true); // Add the anonymous struct/union object to the current // context. We'll be referencing this object when we refer to one of // its members. Owner->addDecl(Anon); // Inject the members of the anonymous struct/union into the owning // context and into the identifier resolver chain for name lookup // purposes. SmallVector Chain; Chain.push_back(Anon); if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS, Chain)) Invalid = true; if (VarDecl *NewVD = dyn_cast(Anon)) { if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) { Decl *ManglingContextDecl; if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext( NewVD->getDeclContext(), ManglingContextDecl)) { Context.setManglingNumber( NewVD, MCtx->getManglingNumber( NewVD, getMSManglingNumber(getLangOpts(), S))); Context.setStaticLocalNumber(NewVD, MCtx->getStaticLocalNumber(NewVD)); } } } if (Invalid) Anon->setInvalidDecl(); return Anon; } /// BuildMicrosoftCAnonymousStruct - Handle the declaration of an /// Microsoft C anonymous structure. /// Ref: http://msdn.microsoft.com/en-us/library/z2cx9y4f.aspx /// Example: /// /// struct A { int a; }; /// struct B { struct A; int b; }; /// /// void foo() { /// B var; /// var.a = 3; /// } /// Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, RecordDecl *Record) { assert(Record && "expected a record!"); // Mock up a declarator. Declarator Dc(DS, Declarator::TypeNameContext); TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S); assert(TInfo && "couldn't build declarator info for anonymous struct"); auto *ParentDecl = cast(CurContext); QualType RecTy = Context.getTypeDeclType(Record); // Create a declaration for this anonymous struct. NamedDecl *Anon = FieldDecl::Create(Context, ParentDecl, DS.getLocStart(), DS.getLocStart(), /*IdentifierInfo=*/nullptr, RecTy, TInfo, /*BitWidth=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); Anon->setImplicit(); // Add the anonymous struct object to the current context. CurContext->addDecl(Anon); // Inject the members of the anonymous struct into the current // context and into the identifier resolver chain for name lookup // purposes. SmallVector Chain; Chain.push_back(Anon); RecordDecl *RecordDef = Record->getDefinition(); if (RequireCompleteType(Anon->getLocation(), RecTy, diag::err_field_incomplete) || InjectAnonymousStructOrUnionMembers(*this, S, CurContext, RecordDef, AS_none, Chain)) { Anon->setInvalidDecl(); ParentDecl->setInvalidDecl(); } return Anon; } /// GetNameForDeclarator - Determine the full declaration name for the /// given Declarator. DeclarationNameInfo Sema::GetNameForDeclarator(Declarator &D) { return GetNameFromUnqualifiedId(D.getName()); } /// \brief Retrieves the declaration name from a parsed unqualified-id. DeclarationNameInfo Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { DeclarationNameInfo NameInfo; NameInfo.setLoc(Name.StartLocation); switch (Name.getKind()) { case UnqualifiedId::IK_ImplicitSelfParam: case UnqualifiedId::IK_Identifier: NameInfo.setName(Name.Identifier); NameInfo.setLoc(Name.StartLocation); return NameInfo; case UnqualifiedId::IK_DeductionGuideName: { // C++ [temp.deduct.guide]p3: // The simple-template-id shall name a class template specialization. // The template-name shall be the same identifier as the template-name // of the simple-template-id. // These together intend to imply that the template-name shall name a // class template. // FIXME: template struct X {}; // template using Y = X; // Y(int) -> Y; // satisfies these rules but does not name a class template. TemplateName TN = Name.TemplateName.get().get(); auto *Template = TN.getAsTemplateDecl(); if (!Template || !isa(Template)) { Diag(Name.StartLocation, diag::err_deduction_guide_name_not_class_template) << (int)getTemplateNameKindForDiagnostics(TN) << TN; if (Template) Diag(Template->getLocation(), diag::note_template_decl_here); return DeclarationNameInfo(); } NameInfo.setName( Context.DeclarationNames.getCXXDeductionGuideName(Template)); NameInfo.setLoc(Name.StartLocation); return NameInfo; } case UnqualifiedId::IK_OperatorFunctionId: NameInfo.setName(Context.DeclarationNames.getCXXOperatorName( Name.OperatorFunctionId.Operator)); NameInfo.setLoc(Name.StartLocation); NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc = Name.OperatorFunctionId.SymbolLocations[0]; NameInfo.getInfo().CXXOperatorName.EndOpNameLoc = Name.EndLocation.getRawEncoding(); return NameInfo; case UnqualifiedId::IK_LiteralOperatorId: NameInfo.setName(Context.DeclarationNames.getCXXLiteralOperatorName( Name.Identifier)); NameInfo.setLoc(Name.StartLocation); NameInfo.setCXXLiteralOperatorNameLoc(Name.EndLocation); return NameInfo; case UnqualifiedId::IK_ConversionFunctionId: { TypeSourceInfo *TInfo; QualType Ty = GetTypeFromParser(Name.ConversionFunctionId, &TInfo); if (Ty.isNull()) return DeclarationNameInfo(); NameInfo.setName(Context.DeclarationNames.getCXXConversionFunctionName( Context.getCanonicalType(Ty))); NameInfo.setLoc(Name.StartLocation); NameInfo.setNamedTypeInfo(TInfo); return NameInfo; } case UnqualifiedId::IK_ConstructorName: { TypeSourceInfo *TInfo; QualType Ty = GetTypeFromParser(Name.ConstructorName, &TInfo); if (Ty.isNull()) return DeclarationNameInfo(); NameInfo.setName(Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(Ty))); NameInfo.setLoc(Name.StartLocation); NameInfo.setNamedTypeInfo(TInfo); return NameInfo; } case UnqualifiedId::IK_ConstructorTemplateId: { // In well-formed code, we can only have a constructor // template-id that refers to the current context, so go there // to find the actual type being constructed. CXXRecordDecl *CurClass = dyn_cast(CurContext); if (!CurClass || CurClass->getIdentifier() != Name.TemplateId->Name) return DeclarationNameInfo(); // Determine the type of the class being constructed. QualType CurClassType = Context.getTypeDeclType(CurClass); // FIXME: Check two things: that the template-id names the same type as // CurClassType, and that the template-id does not occur when the name // was qualified. NameInfo.setName(Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(CurClassType))); NameInfo.setLoc(Name.StartLocation); // FIXME: should we retrieve TypeSourceInfo? NameInfo.setNamedTypeInfo(nullptr); return NameInfo; } case UnqualifiedId::IK_DestructorName: { TypeSourceInfo *TInfo; QualType Ty = GetTypeFromParser(Name.DestructorName, &TInfo); if (Ty.isNull()) return DeclarationNameInfo(); NameInfo.setName(Context.DeclarationNames.getCXXDestructorName( Context.getCanonicalType(Ty))); NameInfo.setLoc(Name.StartLocation); NameInfo.setNamedTypeInfo(TInfo); return NameInfo; } case UnqualifiedId::IK_TemplateId: { TemplateName TName = Name.TemplateId->Template.get(); SourceLocation TNameLoc = Name.TemplateId->TemplateNameLoc; return Context.getNameForTemplate(TName, TNameLoc); } } // switch (Name.getKind()) llvm_unreachable("Unknown name kind"); } static QualType getCoreType(QualType Ty) { do { if (Ty->isPointerType() || Ty->isReferenceType()) Ty = Ty->getPointeeType(); else if (Ty->isArrayType()) Ty = Ty->castAsArrayTypeUnsafe()->getElementType(); else return Ty.withoutLocalFastQualifiers(); } while (true); } /// hasSimilarParameters - Determine whether the C++ functions Declaration /// and Definition have "nearly" matching parameters. This heuristic is /// used to improve diagnostics in the case where an out-of-line function /// definition doesn't match any declaration within the class or namespace. /// Also sets Params to the list of indices to the parameters that differ /// between the declaration and the definition. If hasSimilarParameters /// returns true and Params is empty, then all of the parameters match. static bool hasSimilarParameters(ASTContext &Context, FunctionDecl *Declaration, FunctionDecl *Definition, SmallVectorImpl &Params) { Params.clear(); if (Declaration->param_size() != Definition->param_size()) return false; for (unsigned Idx = 0; Idx < Declaration->param_size(); ++Idx) { QualType DeclParamTy = Declaration->getParamDecl(Idx)->getType(); QualType DefParamTy = Definition->getParamDecl(Idx)->getType(); // The parameter types are identical if (Context.hasSameType(DefParamTy, DeclParamTy)) continue; QualType DeclParamBaseTy = getCoreType(DeclParamTy); QualType DefParamBaseTy = getCoreType(DefParamTy); const IdentifierInfo *DeclTyName = DeclParamBaseTy.getBaseTypeIdentifier(); const IdentifierInfo *DefTyName = DefParamBaseTy.getBaseTypeIdentifier(); if (Context.hasSameUnqualifiedType(DeclParamBaseTy, DefParamBaseTy) || (DeclTyName && DeclTyName == DefTyName)) Params.push_back(Idx); else // The two parameters aren't even close return false; } return true; } /// NeedsRebuildingInCurrentInstantiation - Checks whether the given /// declarator needs to be rebuilt in the current instantiation. /// Any bits of declarator which appear before the name are valid for /// consideration here. That's specifically the type in the decl spec /// and the base type in any member-pointer chunks. static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, DeclarationName Name) { // The types we specifically need to rebuild are: // - typenames, typeofs, and decltypes // - types which will become injected class names // Of course, we also need to rebuild any type referencing such a // type. It's safest to just say "dependent", but we call out a // few cases here. DeclSpec &DS = D.getMutableDeclSpec(); switch (DS.getTypeSpecType()) { case DeclSpec::TST_typename: case DeclSpec::TST_typeofType: case DeclSpec::TST_underlyingType: case DeclSpec::TST_atomic: { // Grab the type from the parser. TypeSourceInfo *TSI = nullptr; QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI); if (T.isNull() || !T->isDependentType()) break; // Make sure there's a type source info. This isn't really much // of a waste; most dependent types should have type source info // attached already. if (!TSI) TSI = S.Context.getTrivialTypeSourceInfo(T, DS.getTypeSpecTypeLoc()); // Rebuild the type in the current instantiation. TSI = S.RebuildTypeInCurrentInstantiation(TSI, D.getIdentifierLoc(), Name); if (!TSI) return true; // Store the new type back in the decl spec. ParsedType LocType = S.CreateParsedType(TSI->getType(), TSI); DS.UpdateTypeRep(LocType); break; } case DeclSpec::TST_decltype: case DeclSpec::TST_typeofExpr: { Expr *E = DS.getRepAsExpr(); ExprResult Result = S.RebuildExprInCurrentInstantiation(E); if (Result.isInvalid()) return true; DS.UpdateExprRep(Result.get()); break; } default: // Nothing to do for these decl specs. break; } // It doesn't matter what order we do this in. for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) { DeclaratorChunk &Chunk = D.getTypeObject(I); // The only type information in the declarator which can come // before the declaration name is the base type of a member // pointer. if (Chunk.Kind != DeclaratorChunk::MemberPointer) continue; // Rebuild the scope specifier in-place. CXXScopeSpec &SS = Chunk.Mem.Scope(); if (S.RebuildNestedNameSpecifierInCurrentInstantiation(SS)) return true; } return false; } Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { D.setFunctionDefinitionKind(FDK_Declaration); Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg()); if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer() && Dcl && Dcl->getDeclContext()->isFileContext()) Dcl->setTopLevelDeclInObjCContainer(); if (getLangOpts().OpenCL) setCurrentOpenCLExtensionForDecl(Dcl); return Dcl; } /// DiagnoseClassNameShadow - Implement C++ [class.mem]p13: /// If T is the name of a class, then each of the following shall have a /// name different from T: /// - every static data member of class T; /// - every member function of class T /// - every member of class T that is itself a type; /// \returns true if the declaration name violates these rules. bool Sema::DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo NameInfo) { DeclarationName Name = NameInfo.getName(); CXXRecordDecl *Record = dyn_cast(DC); while (Record && Record->isAnonymousStructOrUnion()) Record = dyn_cast(Record->getParent()); if (Record && Record->getIdentifier() && Record->getDeclName() == Name) { Diag(NameInfo.getLoc(), diag::err_member_name_of_class) << Name; return true; } return false; } /// \brief Diagnose a declaration whose declarator-id has the given /// nested-name-specifier. /// /// \param SS The nested-name-specifier of the declarator-id. /// /// \param DC The declaration context to which the nested-name-specifier /// resolves. /// /// \param Name The name of the entity being declared. /// /// \param Loc The location of the name of the entity being declared. /// /// \returns true if we cannot safely recover from this error, false otherwise. bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, DeclarationName Name, SourceLocation Loc) { DeclContext *Cur = CurContext; while (isa(Cur) || isa(Cur)) Cur = Cur->getParent(); // If the user provided a superfluous scope specifier that refers back to the // class in which the entity is already declared, diagnose and ignore it. // // class X { // void X::f(); // }; // // Note, it was once ill-formed to give redundant qualification in all // contexts, but that rule was removed by DR482. if (Cur->Equals(DC)) { if (Cur->isRecord()) { Diag(Loc, LangOpts.MicrosoftExt ? diag::warn_member_extra_qualification : diag::err_member_extra_qualification) << Name << FixItHint::CreateRemoval(SS.getRange()); SS.clear(); } else { Diag(Loc, diag::warn_namespace_member_extra_qualification) << Name; } return false; } // Check whether the qualifying scope encloses the scope of the original // declaration. if (!Cur->Encloses(DC)) { if (Cur->isRecord()) Diag(Loc, diag::err_member_qualification) << Name << SS.getRange(); else if (isa(DC)) Diag(Loc, diag::err_invalid_declarator_global_scope) << Name << SS.getRange(); else if (isa(Cur)) Diag(Loc, diag::err_invalid_declarator_in_function) << Name << SS.getRange(); else if (isa(Cur)) Diag(Loc, diag::err_invalid_declarator_in_block) << Name << SS.getRange(); else Diag(Loc, diag::err_invalid_declarator_scope) << Name << cast(Cur) << cast(DC) << SS.getRange(); return true; } if (Cur->isRecord()) { // Cannot qualify members within a class. Diag(Loc, diag::err_member_qualification) << Name << SS.getRange(); SS.clear(); // C++ constructors and destructors with incorrect scopes can break // our AST invariants by having the wrong underlying types. If // that's the case, then drop this declaration entirely. if ((Name.getNameKind() == DeclarationName::CXXConstructorName || Name.getNameKind() == DeclarationName::CXXDestructorName) && !Context.hasSameType(Name.getCXXNameType(), Context.getTypeDeclType(cast(Cur)))) return true; return false; } // C++11 [dcl.meaning]p1: // [...] "The nested-name-specifier of the qualified declarator-id shall // not begin with a decltype-specifer" NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data()); while (SpecLoc.getPrefix()) SpecLoc = SpecLoc.getPrefix(); if (dyn_cast_or_null( SpecLoc.getNestedNameSpecifier()->getAsType())) Diag(Loc, diag::err_decltype_in_declarator) << SpecLoc.getTypeLoc().getSourceRange(); return false; } NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists) { // TODO: consider using NameInfo for diagnostic. DeclarationNameInfo NameInfo = GetNameForDeclarator(D); DeclarationName Name = NameInfo.getName(); // All of these full declarators require an identifier. If it doesn't have // one, the ParsedFreeStandingDeclSpec action should be used. if (D.isDecompositionDeclarator()) { return ActOnDecompositionDeclarator(S, D, TemplateParamLists); } else if (!Name) { if (!D.isInvalidType()) // Reject this if we think it is valid. Diag(D.getDeclSpec().getLocStart(), diag::err_declarator_need_ident) << D.getDeclSpec().getSourceRange() << D.getSourceRange(); return nullptr; } else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType)) return nullptr; // The scope passed in may not be a decl scope. Zip up the scope tree until // we find one that is. while ((S->getFlags() & Scope::DeclScope) == 0 || (S->getFlags() & Scope::TemplateParamScope) != 0) S = S->getParent(); DeclContext *DC = CurContext; if (D.getCXXScopeSpec().isInvalid()) D.setInvalidType(); else if (D.getCXXScopeSpec().isSet()) { if (DiagnoseUnexpandedParameterPack(D.getCXXScopeSpec(), UPPC_DeclarationQualifier)) return nullptr; bool EnteringContext = !D.getDeclSpec().isFriendSpecified(); DC = computeDeclContext(D.getCXXScopeSpec(), EnteringContext); if (!DC || isa(DC)) { // If we could not compute the declaration context, it's because the // declaration context is dependent but does not refer to a class, // class template, or class template partial specialization. Complain // and return early, to avoid the coming semantic disaster. Diag(D.getIdentifierLoc(), diag::err_template_qualified_declarator_no_match) << D.getCXXScopeSpec().getScopeRep() << D.getCXXScopeSpec().getRange(); return nullptr; } bool IsDependentContext = DC->isDependentContext(); if (!IsDependentContext && RequireCompleteDeclContext(D.getCXXScopeSpec(), DC)) return nullptr; // If a class is incomplete, do not parse entities inside it. if (isa(DC) && !cast(DC)->hasDefinition()) { Diag(D.getIdentifierLoc(), diag::err_member_def_undefined_record) << Name << DC << D.getCXXScopeSpec().getRange(); return nullptr; } if (!D.getDeclSpec().isFriendSpecified()) { if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC, Name, D.getIdentifierLoc())) { if (DC->isRecord()) return nullptr; D.setInvalidType(); } } // Check whether we need to rebuild the type of the given // declaration in the current instantiation. if (EnteringContext && IsDependentContext && TemplateParamLists.size() != 0) { ContextRAII SavedContext(*this, DC); if (RebuildDeclaratorInCurrentInstantiation(*this, D, Name)) D.setInvalidType(); } } TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType R = TInfo->getType(); if (!R->isFunctionType() && DiagnoseClassNameShadow(DC, NameInfo)) // If this is a typedef, we'll end up spewing multiple diagnostics. // Just return early; it's safer. If this is a function, let the // "constructor cannot have a return type" diagnostic handle it. if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) return nullptr; if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, UPPC_DeclarationType)) D.setInvalidType(); LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); // See if this is a redefinition of a variable in the same scope. if (!D.getCXXScopeSpec().isSet()) { bool IsLinkageLookup = false; bool CreateBuiltins = false; // If the declaration we're planning to build will be a function // or object with linkage, then look for another declaration with // linkage (C99 6.2.2p4-5 and C++ [basic.link]p6). // // If the declaration we're planning to build will be declared with // external linkage in the translation unit, create any builtin with // the same name. if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) /* Do nothing*/; else if (CurContext->isFunctionOrMethod() && (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern || R->isFunctionType())) { IsLinkageLookup = true; CreateBuiltins = CurContext->getEnclosingNamespaceContext()->isTranslationUnit(); } else if (CurContext->getRedeclContext()->isTranslationUnit() && D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) CreateBuiltins = true; if (IsLinkageLookup) Previous.clear(LookupRedeclarationWithLinkage); LookupName(Previous, S, CreateBuiltins); } else { // Something like "int foo::x;" LookupQualifiedName(Previous, DC); // C++ [dcl.meaning]p1: // When the declarator-id is qualified, the declaration shall refer to a // previously declared member of the class or namespace to which the // qualifier refers (or, in the case of a namespace, of an element of the // inline namespace set of that namespace (7.3.1)) or to a specialization // thereof; [...] // // Note that we already checked the context above, and that we do not have // enough information to make sure that Previous contains the declaration // we want to match. For example, given: // // class X { // void f(); // void f(float); // }; // // void X::f(int) { } // ill-formed // // In this case, Previous will point to the overload set // containing the two f's declared in X, but neither of them // matches. // C++ [dcl.meaning]p1: // [...] the member shall not merely have been introduced by a // using-declaration in the scope of the class or namespace nominated by // the nested-name-specifier of the declarator-id. RemoveUsingDecls(Previous); } if (Previous.isSingleResult() && Previous.getFoundDecl()->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. if (!D.isInvalidType()) DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), Previous.getFoundDecl()); // Just pretend that we didn't see the previous declaration. Previous.clear(); } // In C++, the previous declaration we find might be a tag type // (class or enum). In this case, the new declaration will hide the // tag type. Note that this does does not apply if we're declaring a // typedef (C++ [dcl.typedef]p4). if (Previous.isSingleTagDecl() && D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef) Previous.clear(); // Check that there are no default arguments other than in the parameters // of a function declaration (C++ only). if (getLangOpts().CPlusPlus) CheckExtraCXXDefaultArguments(D); if (D.getDeclSpec().isConceptSpecified()) { // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be // applied only to the definition of a function template or variable // template, declared in namespace scope if (!TemplateParamLists.size()) { Diag(D.getDeclSpec().getConceptSpecLoc(), diag:: err_concept_wrong_decl_kind); return nullptr; } if (!DC->getRedeclContext()->isFileContext()) { Diag(D.getIdentifierLoc(), diag::err_concept_decls_may_only_appear_in_namespace_scope); return nullptr; } } NamedDecl *New; bool AddToScope = true; if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { if (TemplateParamLists.size()) { Diag(D.getIdentifierLoc(), diag::err_template_typedef); return nullptr; } New = ActOnTypedefDeclarator(S, D, DC, TInfo, Previous); } else if (R->isFunctionType()) { New = ActOnFunctionDeclarator(S, D, DC, TInfo, Previous, TemplateParamLists, AddToScope); } else { New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous, TemplateParamLists, AddToScope); } if (!New) return nullptr; // If this has an identifier and is not a function template specialization, // add it to the scope stack. if (New->getDeclName() && AddToScope) { // Only make a locally-scoped extern declaration visible if it is the first // declaration of this entity. Qualified lookup for such an entity should // only find this declaration if there is no visible declaration of it. bool AddToContext = !D.isRedeclaration() || !New->isLocalExternDecl(); PushOnScopeChains(New, S, AddToContext); if (!AddToContext) CurContext->addHiddenDecl(New); } if (isInOpenMPDeclareTargetContext()) checkDeclIsAllowedInOpenMPTarget(nullptr, New); return New; } /// Helper method to turn variable array types into constant array /// types in certain situations which would otherwise be errors (for /// GCC compatibility). static QualType TryToFixInvalidVariablyModifiedType(QualType T, ASTContext &Context, bool &SizeIsNegative, llvm::APSInt &Oversized) { // This method tries to turn a variable array into a constant // array even when the size isn't an ICE. This is necessary // for compatibility with code that depends on gcc's buggy // constant expression folding, like struct {char x[(int)(char*)2];} SizeIsNegative = false; Oversized = 0; if (T->isDependentType()) return QualType(); QualifierCollector Qs; const Type *Ty = Qs.strip(T); if (const PointerType* PTy = dyn_cast(Ty)) { QualType Pointee = PTy->getPointeeType(); QualType FixedType = TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative, Oversized); if (FixedType.isNull()) return FixedType; FixedType = Context.getPointerType(FixedType); return Qs.apply(Context, FixedType); } if (const ParenType* PTy = dyn_cast(Ty)) { QualType Inner = PTy->getInnerType(); QualType FixedType = TryToFixInvalidVariablyModifiedType(Inner, Context, SizeIsNegative, Oversized); if (FixedType.isNull()) return FixedType; FixedType = Context.getParenType(FixedType); return Qs.apply(Context, FixedType); } const VariableArrayType* VLATy = dyn_cast(T); if (!VLATy) return QualType(); // FIXME: We should probably handle this case if (VLATy->getElementType()->isVariablyModifiedType()) return QualType(); llvm::APSInt Res; if (!VLATy->getSizeExpr() || !VLATy->getSizeExpr()->EvaluateAsInt(Res, Context)) return QualType(); // Check whether the array size is negative. if (Res.isSigned() && Res.isNegative()) { SizeIsNegative = true; return QualType(); } // Check whether the array is too large to be addressed. unsigned ActiveSizeBits = ConstantArrayType::getNumAddressingBits(Context, VLATy->getElementType(), Res); if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) { Oversized = Res; return QualType(); } return Context.getConstantArrayType(VLATy->getElementType(), Res, ArrayType::Normal, 0); } static void FixInvalidVariablyModifiedTypeLoc(TypeLoc SrcTL, TypeLoc DstTL) { SrcTL = SrcTL.getUnqualifiedLoc(); DstTL = DstTL.getUnqualifiedLoc(); if (PointerTypeLoc SrcPTL = SrcTL.getAs()) { PointerTypeLoc DstPTL = DstTL.castAs(); FixInvalidVariablyModifiedTypeLoc(SrcPTL.getPointeeLoc(), DstPTL.getPointeeLoc()); DstPTL.setStarLoc(SrcPTL.getStarLoc()); return; } if (ParenTypeLoc SrcPTL = SrcTL.getAs()) { ParenTypeLoc DstPTL = DstTL.castAs(); FixInvalidVariablyModifiedTypeLoc(SrcPTL.getInnerLoc(), DstPTL.getInnerLoc()); DstPTL.setLParenLoc(SrcPTL.getLParenLoc()); DstPTL.setRParenLoc(SrcPTL.getRParenLoc()); return; } ArrayTypeLoc SrcATL = SrcTL.castAs(); ArrayTypeLoc DstATL = DstTL.castAs(); TypeLoc SrcElemTL = SrcATL.getElementLoc(); TypeLoc DstElemTL = DstATL.getElementLoc(); DstElemTL.initializeFullCopy(SrcElemTL); DstATL.setLBracketLoc(SrcATL.getLBracketLoc()); DstATL.setSizeExpr(SrcATL.getSizeExpr()); DstATL.setRBracketLoc(SrcATL.getRBracketLoc()); } /// Helper method to turn variable array types into constant array /// types in certain situations which would otherwise be errors (for /// GCC compatibility). static TypeSourceInfo* TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo, ASTContext &Context, bool &SizeIsNegative, llvm::APSInt &Oversized) { QualType FixedTy = TryToFixInvalidVariablyModifiedType(TInfo->getType(), Context, SizeIsNegative, Oversized); if (FixedTy.isNull()) return nullptr; TypeSourceInfo *FixedTInfo = Context.getTrivialTypeSourceInfo(FixedTy); FixInvalidVariablyModifiedTypeLoc(TInfo->getTypeLoc(), FixedTInfo->getTypeLoc()); return FixedTInfo; } /// \brief Register the given locally-scoped extern "C" declaration so /// that it can be found later for redeclarations. We include any extern "C" /// declaration that is not visible in the translation unit here, not just /// function-scope declarations. void Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S) { if (!getLangOpts().CPlusPlus && ND->getLexicalDeclContext()->getRedeclContext()->isTranslationUnit()) // Don't need to track declarations in the TU in C. return; // Note that we have a locally-scoped external with this name. Context.getExternCContextDecl()->makeDeclVisibleInContext(ND); } NamedDecl *Sema::findLocallyScopedExternCDecl(DeclarationName Name) { // FIXME: We can have multiple results via __attribute__((overloadable)). auto Result = Context.getExternCContextDecl()->lookup(Name); return Result.empty() ? nullptr : *Result.begin(); } /// \brief Diagnose function specifiers on a declaration of an identifier that /// does not identify a function. void Sema::DiagnoseFunctionSpecifiers(const DeclSpec &DS) { // FIXME: We should probably indicate the identifier in question to avoid // confusion for constructs like "virtual int a(), b;" if (DS.isVirtualSpecified()) Diag(DS.getVirtualSpecLoc(), diag::err_virtual_non_function); if (DS.isExplicitSpecified()) Diag(DS.getExplicitSpecLoc(), diag::err_explicit_non_function); if (DS.isNoreturnSpecified()) Diag(DS.getNoreturnSpecLoc(), diag::err_noreturn_non_function); } NamedDecl* Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, TypeSourceInfo *TInfo, LookupResult &Previous) { // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1). if (D.getCXXScopeSpec().isSet()) { Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator) << D.getCXXScopeSpec().getRange(); D.setInvalidType(); // Pretend we didn't see the scope specifier. DC = CurContext; Previous.clear(); } DiagnoseFunctionSpecifiers(D.getDeclSpec()); if (D.getDeclSpec().isInlineSpecified()) Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function) << getLangOpts().CPlusPlus1z; if (D.getDeclSpec().isConstexprSpecified()) Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) << 1; if (D.getDeclSpec().isConceptSpecified()) Diag(D.getDeclSpec().getConceptSpecLoc(), diag::err_concept_wrong_decl_kind); if (D.getName().Kind != UnqualifiedId::IK_Identifier) { if (D.getName().Kind == UnqualifiedId::IK_DeductionGuideName) Diag(D.getName().StartLocation, diag::err_deduction_guide_invalid_specifier) << "typedef"; else Diag(D.getName().StartLocation, diag::err_typedef_not_identifier) << D.getName().getSourceRange(); return nullptr; } TypedefDecl *NewTD = ParseTypedefDecl(S, D, TInfo->getType(), TInfo); if (!NewTD) return nullptr; // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewTD, D); CheckTypedefForVariablyModifiedType(S, NewTD); bool Redeclaration = D.isRedeclaration(); NamedDecl *ND = ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration); D.setRedeclaration(Redeclaration); return ND; } void Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) { // C99 6.7.7p2: If a typedef name specifies a variably modified type // then it shall have block scope. // Note that variably modified types must be fixed before merging the decl so // that redeclarations will match. TypeSourceInfo *TInfo = NewTD->getTypeSourceInfo(); QualType T = TInfo->getType(); if (T->isVariablyModifiedType()) { getCurFunction()->setHasBranchProtectedScope(); if (S->getFnParent() == nullptr) { bool SizeIsNegative; llvm::APSInt Oversized; TypeSourceInfo *FixedTInfo = TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context, SizeIsNegative, Oversized); if (FixedTInfo) { Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size); NewTD->setTypeSourceInfo(FixedTInfo); } else { if (SizeIsNegative) Diag(NewTD->getLocation(), diag::err_typecheck_negative_array_size); else if (T->isVariableArrayType()) Diag(NewTD->getLocation(), diag::err_vla_decl_in_file_scope); else if (Oversized.getBoolValue()) Diag(NewTD->getLocation(), diag::err_array_too_large) << Oversized.toString(10); else Diag(NewTD->getLocation(), diag::err_vm_decl_in_file_scope); NewTD->setInvalidDecl(); } } } } /// ActOnTypedefNameDecl - Perform semantic checking for a declaration which /// declares a typedef-name, either using the 'typedef' type specifier or via /// a C++0x [dcl.typedef]p2 alias-declaration: 'using T = A;'. NamedDecl* Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, LookupResult &Previous, bool &Redeclaration) { // Find the shadowed declaration before filtering for scope. NamedDecl *ShadowedDecl = getShadowedDeclaration(NewTD, Previous); // Merge the decl with the existing one if appropriate. If the decl is // in an outer scope, it isn't the same thing. FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/false, /*AllowInlineNamespace*/false); filterNonConflictingPreviousTypedefDecls(*this, NewTD, Previous); if (!Previous.empty()) { Redeclaration = true; MergeTypedefNameDecl(S, NewTD, Previous); } if (ShadowedDecl && !Redeclaration) CheckShadow(NewTD, ShadowedDecl, Previous); // If this is the C FILE type, notify the AST context. if (IdentifierInfo *II = NewTD->getIdentifier()) if (!NewTD->isInvalidDecl() && NewTD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { if (II->isStr("FILE")) Context.setFILEDecl(NewTD); else if (II->isStr("jmp_buf")) Context.setjmp_bufDecl(NewTD); else if (II->isStr("sigjmp_buf")) Context.setsigjmp_bufDecl(NewTD); else if (II->isStr("ucontext_t")) Context.setucontext_tDecl(NewTD); } return NewTD; } /// \brief Determines whether the given declaration is an out-of-scope /// previous declaration. /// /// This routine should be invoked when name lookup has found a /// previous declaration (PrevDecl) that is not in the scope where a /// new declaration by the same name is being introduced. If the new /// declaration occurs in a local scope, previous declarations with /// linkage may still be considered previous declarations (C99 /// 6.2.2p4-5, C++ [basic.link]p6). /// /// \param PrevDecl the previous declaration found by name /// lookup /// /// \param DC the context in which the new declaration is being /// declared. /// /// \returns true if PrevDecl is an out-of-scope previous declaration /// for a new delcaration with the same name. static bool isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, ASTContext &Context) { if (!PrevDecl) return false; if (!PrevDecl->hasLinkage()) return false; if (Context.getLangOpts().CPlusPlus) { // C++ [basic.link]p6: // If there is a visible declaration of an entity with linkage // having the same name and type, ignoring entities declared // outside the innermost enclosing namespace scope, the block // scope declaration declares that same entity and receives the // linkage of the previous declaration. DeclContext *OuterContext = DC->getRedeclContext(); if (!OuterContext->isFunctionOrMethod()) // This rule only applies to block-scope declarations. return false; DeclContext *PrevOuterContext = PrevDecl->getDeclContext(); if (PrevOuterContext->isRecord()) // We found a member function: ignore it. return false; // Find the innermost enclosing namespace for the new and // previous declarations. OuterContext = OuterContext->getEnclosingNamespaceContext(); PrevOuterContext = PrevOuterContext->getEnclosingNamespaceContext(); // The previous declaration is in a different namespace, so it // isn't the same function. if (!OuterContext->Equals(PrevOuterContext)) return false; } return true; } static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) { CXXScopeSpec &SS = D.getCXXScopeSpec(); if (!SS.isSet()) return; DD->setQualifierInfo(SS.getWithLocInContext(DD->getASTContext())); } bool Sema::inferObjCARCLifetime(ValueDecl *decl) { QualType type = decl->getType(); Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime(); if (lifetime == Qualifiers::OCL_Autoreleasing) { // Various kinds of declaration aren't allowed to be __autoreleasing. unsigned kind = -1U; if (VarDecl *var = dyn_cast(decl)) { if (var->hasAttr()) kind = 0; // __block else if (!var->hasLocalStorage()) kind = 1; // global } else if (isa(decl)) { kind = 3; // ivar } else if (isa(decl)) { kind = 2; // field } if (kind != -1U) { Diag(decl->getLocation(), diag::err_arc_autoreleasing_var) << kind; } } else if (lifetime == Qualifiers::OCL_None) { // Try to infer lifetime. if (!type->isObjCLifetimeType()) return false; lifetime = type->getObjCARCImplicitLifetime(); type = Context.getLifetimeQualifiedType(type, lifetime); decl->setType(type); } if (VarDecl *var = dyn_cast(decl)) { // Thread-local variables cannot have lifetime. if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone && var->getTLSKind()) { Diag(var->getLocation(), diag::err_arc_thread_ownership) << var->getType(); return true; } } return false; } static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { // Ensure that an auto decl is deduced otherwise the checks below might cache // the wrong linkage. assert(S.ParsingInitForAutoVars.count(&ND) == 0); // 'weak' only applies to declarations with external linkage. if (WeakAttr *Attr = ND.getAttr()) { if (!ND.isExternallyVisible()) { S.Diag(Attr->getLocation(), diag::err_attribute_weak_static); ND.dropAttr(); } } if (WeakRefAttr *Attr = ND.getAttr()) { if (ND.isExternallyVisible()) { S.Diag(Attr->getLocation(), diag::err_attribute_weakref_not_static); ND.dropAttr(); ND.dropAttr(); } } if (auto *VD = dyn_cast(&ND)) { if (VD->hasInit()) { if (const auto *Attr = VD->getAttr()) { assert(VD->isThisDeclarationADefinition() && !VD->isExternallyVisible() && "Broken AliasAttr handled late!"); S.Diag(Attr->getLocation(), diag::err_alias_is_definition) << VD << 0; VD->dropAttr(); } } } // 'selectany' only applies to externally visible variable declarations. // It does not apply to functions. if (SelectAnyAttr *Attr = ND.getAttr()) { if (isa(ND) || !ND.isExternallyVisible()) { S.Diag(Attr->getLocation(), diag::err_attribute_selectany_non_extern_data); ND.dropAttr(); } } if (const InheritableAttr *Attr = getDLLAttr(&ND)) { // dll attributes require external linkage. Static locals may have external // linkage but still cannot be explicitly imported or exported. auto *VD = dyn_cast(&ND); if (!ND.isExternallyVisible() || (VD && VD->isStaticLocal())) { S.Diag(ND.getLocation(), diag::err_attribute_dll_not_extern) << &ND << Attr; ND.setInvalidDecl(); } } // Virtual functions cannot be marked as 'notail'. if (auto *Attr = ND.getAttr()) if (auto *MD = dyn_cast(&ND)) if (MD->isVirtual()) { S.Diag(ND.getLocation(), diag::err_invalid_attribute_on_virtual_function) << Attr; ND.dropAttr(); } } static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, NamedDecl *NewDecl, bool IsSpecialization, bool IsDefinition) { if (OldDecl->isInvalidDecl()) return; bool IsTemplate = false; if (TemplateDecl *OldTD = dyn_cast(OldDecl)) { OldDecl = OldTD->getTemplatedDecl(); IsTemplate = true; if (!IsSpecialization) IsDefinition = false; } if (TemplateDecl *NewTD = dyn_cast(NewDecl)) { NewDecl = NewTD->getTemplatedDecl(); IsTemplate = true; } if (!OldDecl || !NewDecl) return; const DLLImportAttr *OldImportAttr = OldDecl->getAttr(); const DLLExportAttr *OldExportAttr = OldDecl->getAttr(); const DLLImportAttr *NewImportAttr = NewDecl->getAttr(); const DLLExportAttr *NewExportAttr = NewDecl->getAttr(); // dllimport and dllexport are inheritable attributes so we have to exclude // inherited attribute instances. bool HasNewAttr = (NewImportAttr && !NewImportAttr->isInherited()) || (NewExportAttr && !NewExportAttr->isInherited()); // A redeclaration is not allowed to add a dllimport or dllexport attribute, // the only exception being explicit specializations. // Implicitly generated declarations are also excluded for now because there // is no other way to switch these to use dllimport or dllexport. bool AddsAttr = !(OldImportAttr || OldExportAttr) && HasNewAttr; if (AddsAttr && !IsSpecialization && !OldDecl->isImplicit()) { // Allow with a warning for free functions and global variables. bool JustWarn = false; if (!OldDecl->isCXXClassMember()) { auto *VD = dyn_cast(OldDecl); if (VD && !VD->getDescribedVarTemplate()) JustWarn = true; auto *FD = dyn_cast(OldDecl); if (FD && FD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) JustWarn = true; } // We cannot change a declaration that's been used because IR has already // been emitted. Dllimported functions will still work though (modulo // address equality) as they can use the thunk. if (OldDecl->isUsed()) if (!isa(OldDecl) || !NewImportAttr) JustWarn = false; unsigned DiagID = JustWarn ? diag::warn_attribute_dll_redeclaration : diag::err_attribute_dll_redeclaration; S.Diag(NewDecl->getLocation(), DiagID) << NewDecl << (NewImportAttr ? (const Attr *)NewImportAttr : NewExportAttr); S.Diag(OldDecl->getLocation(), diag::note_previous_declaration); if (!JustWarn) { NewDecl->setInvalidDecl(); return; } } // A redeclaration is not allowed to drop a dllimport attribute, the only // exceptions being inline function definitions (except for function // templates), local extern declarations, qualified friend declarations or // special MSVC extension: in the last case, the declaration is treated as if // it were marked dllexport. bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false; bool IsMicrosoft = S.Context.getTargetInfo().getCXXABI().isMicrosoft(); if (const auto *VD = dyn_cast(NewDecl)) { // Ignore static data because out-of-line definitions are diagnosed // separately. IsStaticDataMember = VD->isStaticDataMember(); IsDefinition = VD->isThisDeclarationADefinition(S.Context) != VarDecl::DeclarationOnly; } else if (const auto *FD = dyn_cast(NewDecl)) { IsInline = FD->isInlined(); IsQualifiedFriend = FD->getQualifier() && FD->getFriendObjectKind() == Decl::FOK_Declared; } if (OldImportAttr && !HasNewAttr && (!IsInline || (IsMicrosoft && IsTemplate)) && !IsStaticDataMember && !NewDecl->isLocalExternDecl() && !IsQualifiedFriend) { if (IsMicrosoft && IsDefinition) { S.Diag(NewDecl->getLocation(), diag::warn_redeclaration_without_import_attribute) << NewDecl; S.Diag(OldDecl->getLocation(), diag::note_previous_declaration); NewDecl->dropAttr(); NewDecl->addAttr(::new (S.Context) DLLExportAttr( NewImportAttr->getRange(), S.Context, NewImportAttr->getSpellingListIndex())); } else { S.Diag(NewDecl->getLocation(), diag::warn_redeclaration_without_attribute_prev_attribute_ignored) << NewDecl << OldImportAttr; S.Diag(OldDecl->getLocation(), diag::note_previous_declaration); S.Diag(OldImportAttr->getLocation(), diag::note_previous_attribute); OldDecl->dropAttr(); NewDecl->dropAttr(); } } else if (IsInline && OldImportAttr && !IsMicrosoft) { // In MinGW, seeing a function declared inline drops the dllimport attribute. OldDecl->dropAttr(); NewDecl->dropAttr(); S.Diag(NewDecl->getLocation(), diag::warn_dllimport_dropped_from_inline_function) << NewDecl << OldImportAttr; } } /// Given that we are within the definition of the given function, /// will that definition behave like C99's 'inline', where the /// definition is discarded except for optimization purposes? static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) { // Try to avoid calling GetGVALinkageForFunction. // All cases of this require the 'inline' keyword. if (!FD->isInlined()) return false; // This is only possible in C++ with the gnu_inline attribute. if (S.getLangOpts().CPlusPlus && !FD->hasAttr()) return false; // Okay, go ahead and call the relatively-more-expensive function. return S.Context.GetGVALinkageForFunction(FD) == GVA_AvailableExternally; } /// Determine whether a variable is extern "C" prior to attaching /// an initializer. We can't just call isExternC() here, because that /// will also compute and cache whether the declaration is externally /// visible, which might change when we attach the initializer. /// /// This can only be used if the declaration is known to not be a /// redeclaration of an internal linkage declaration. /// /// For instance: /// /// auto x = []{}; /// /// Attaching the initializer here makes this declaration not externally /// visible, because its type has internal linkage. /// /// FIXME: This is a hack. template static bool isIncompleteDeclExternC(Sema &S, const T *D) { if (S.getLangOpts().CPlusPlus) { // In C++, the overloadable attribute negates the effects of extern "C". if (!D->isInExternCContext() || D->template hasAttr()) return false; // So do CUDA's host/device attributes. if (S.getLangOpts().CUDA && (D->template hasAttr() || D->template hasAttr())) return false; } return D->isExternC(); } static bool shouldConsiderLinkage(const VarDecl *VD) { const DeclContext *DC = VD->getDeclContext()->getRedeclContext(); if (DC->isFunctionOrMethod() || isa(DC)) return VD->hasExternalStorage(); if (DC->isFileContext()) return true; if (DC->isRecord()) return false; llvm_unreachable("Unexpected context"); } static bool shouldConsiderLinkage(const FunctionDecl *FD) { const DeclContext *DC = FD->getDeclContext()->getRedeclContext(); if (DC->isFileContext() || DC->isFunctionOrMethod() || isa(DC)) return true; if (DC->isRecord()) return false; llvm_unreachable("Unexpected context"); } static bool hasParsedAttr(Scope *S, const AttributeList *AttrList, AttributeList::Kind Kind) { for (const AttributeList *L = AttrList; L; L = L->getNext()) if (L->getKind() == Kind) return true; return false; } static bool hasParsedAttr(Scope *S, const Declarator &PD, AttributeList::Kind Kind) { // Check decl attributes on the DeclSpec. if (hasParsedAttr(S, PD.getDeclSpec().getAttributes().getList(), Kind)) return true; // Walk the declarator structure, checking decl attributes that were in a type // position to the decl itself. for (unsigned I = 0, E = PD.getNumTypeObjects(); I != E; ++I) { if (hasParsedAttr(S, PD.getTypeObject(I).getAttrs(), Kind)) return true; } // Finally, check attributes on the decl itself. return hasParsedAttr(S, PD.getAttributes(), Kind); } /// Adjust the \c DeclContext for a function or variable that might be a /// function-local external declaration. bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) { if (!DC->isFunctionOrMethod()) return false; // If this is a local extern function or variable declared within a function // template, don't add it into the enclosing namespace scope until it is // instantiated; it might have a dependent type right now. if (DC->isDependentContext()) return true; // C++11 [basic.link]p7: // When a block scope declaration of an entity with linkage is not found to // refer to some other declaration, then that entity is a member of the // innermost enclosing namespace. // // Per C++11 [namespace.def]p6, the innermost enclosing namespace is a // semantically-enclosing namespace, not a lexically-enclosing one. while (!DC->isFileContext() && !isa(DC)) DC = DC->getParent(); return true; } /// \brief Returns true if given declaration has external C language linkage. static bool isDeclExternC(const Decl *D) { if (const auto *FD = dyn_cast(D)) return FD->isExternC(); if (const auto *VD = dyn_cast(D)) return VD->isExternC(); llvm_unreachable("Unknown type of decl!"); } NamedDecl *Sema::ActOnVariableDeclarator( Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, bool &AddToScope, ArrayRef Bindings) { QualType R = TInfo->getType(); DeclarationName Name = GetNameForDeclarator(D).getName(); IdentifierInfo *II = Name.getAsIdentifierInfo(); if (D.isDecompositionDeclarator()) { - AddToScope = false; // Take the name of the first declarator as our name for diagnostic // purposes. auto &Decomp = D.getDecompositionDeclarator(); if (!Decomp.bindings().empty()) { II = Decomp.bindings()[0].Name; Name = II; } } else if (!II) { Diag(D.getIdentifierLoc(), diag::err_bad_variable_name) << Name; return nullptr; } if (getLangOpts().OpenCL) { // OpenCL v2.0 s6.9.b - Image type can only be used as a function argument. // OpenCL v2.0 s6.13.16.1 - Pipe type can only be used as a function // argument. if (R->isImageType() || R->isPipeType()) { Diag(D.getIdentifierLoc(), diag::err_opencl_type_can_only_be_used_as_function_parameter) << R; D.setInvalidType(); return nullptr; } // OpenCL v1.2 s6.9.r: // The event type cannot be used to declare a program scope variable. // OpenCL v2.0 s6.9.q: // The clk_event_t and reserve_id_t types cannot be declared in program scope. if (NULL == S->getParent()) { if (R->isReserveIDT() || R->isClkEventT() || R->isEventT()) { Diag(D.getIdentifierLoc(), diag::err_invalid_type_for_program_scope_var) << R; D.setInvalidType(); return nullptr; } } // OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed. QualType NR = R; while (NR->isPointerType()) { if (NR->isFunctionPointerType()) { Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer); D.setInvalidType(); break; } NR = NR->getPointeeType(); } if (!getOpenCLOptions().isEnabled("cl_khr_fp16")) { // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and // half array type (unless the cl_khr_fp16 extension is enabled). if (Context.getBaseElementType(R)->isHalfType()) { Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R; D.setInvalidType(); } } if (R->isSamplerT()) { // OpenCL v1.2 s6.9.b p4: // The sampler type cannot be used with the __local and __global address // space qualifiers. if (R.getAddressSpace() == LangAS::opencl_local || R.getAddressSpace() == LangAS::opencl_global) { Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace); } // OpenCL v1.2 s6.12.14.1: // A global sampler must be declared with either the constant address // space qualifier or with the const qualifier. if (DC->isTranslationUnit() && !(R.getAddressSpace() == LangAS::opencl_constant || R.isConstQualified())) { Diag(D.getIdentifierLoc(), diag::err_opencl_nonconst_global_sampler); D.setInvalidType(); } } // OpenCL v1.2 s6.9.r: // The event type cannot be used with the __local, __constant and __global // address space qualifiers. if (R->isEventT()) { if (R.getAddressSpace()) { Diag(D.getLocStart(), diag::err_event_t_addr_space_qual); D.setInvalidType(); } } } DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec(); StorageClass SC = StorageClassSpecToVarDeclStorageClass(D.getDeclSpec()); // dllimport globals without explicit storage class are treated as extern. We // have to change the storage class this early to get the right DeclContext. if (SC == SC_None && !DC->isRecord() && hasParsedAttr(S, D, AttributeList::AT_DLLImport) && !hasParsedAttr(S, D, AttributeList::AT_DLLExport)) SC = SC_Extern; DeclContext *OriginalDC = DC; bool IsLocalExternDecl = SC == SC_Extern && adjustContextForLocalExternDecl(DC); if (SCSpec == DeclSpec::SCS_mutable) { // mutable can only appear on non-static class members, so it's always // an error here Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember); D.setInvalidType(); SC = SC_None; } if (getLangOpts().CPlusPlus11 && SCSpec == DeclSpec::SCS_register && !D.getAsmLabel() && !getSourceManager().isInSystemMacro( D.getDeclSpec().getStorageClassSpecLoc())) { // In C++11, the 'register' storage class specifier is deprecated. // Suppress the warning in system macros, it's used in macros in some // popular C system headers, such as in glibc's htonl() macro. Diag(D.getDeclSpec().getStorageClassSpecLoc(), getLangOpts().CPlusPlus1z ? diag::ext_register_storage_class : diag::warn_deprecated_register) << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); } DiagnoseFunctionSpecifiers(D.getDeclSpec()); if (!DC->isRecord() && S->getFnParent() == nullptr) { // C99 6.9p2: The storage-class specifiers auto and register shall not // appear in the declaration specifiers in an external declaration. // Global Register+Asm is a GNU extension we support. if (SC == SC_Auto || (SC == SC_Register && !D.getAsmLabel())) { Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope); D.setInvalidType(); } } bool IsMemberSpecialization = false; bool IsVariableTemplateSpecialization = false; bool IsPartialSpecialization = false; bool IsVariableTemplate = false; VarDecl *NewVD = nullptr; VarTemplateDecl *NewTemplate = nullptr; TemplateParameterList *TemplateParams = nullptr; if (!getLangOpts().CPlusPlus) { NewVD = VarDecl::Create(Context, DC, D.getLocStart(), D.getIdentifierLoc(), II, R, TInfo, SC); if (R->getContainedDeducedType()) ParsingInitForAutoVars.insert(NewVD); if (D.isInvalidType()) NewVD->setInvalidDecl(); } else { bool Invalid = false; if (DC->isRecord() && !CurContext->isRecord()) { // This is an out-of-line definition of a static data member. switch (SC) { case SC_None: break; case SC_Static: Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::err_static_out_of_line) << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); break; case SC_Auto: case SC_Register: case SC_Extern: // [dcl.stc] p2: The auto or register specifiers shall be applied only // to names of variables declared in a block or to function parameters. // [dcl.stc] p6: The extern specifier cannot be used in the declaration // of class members Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::err_storage_class_for_static_member) << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); break; case SC_PrivateExtern: llvm_unreachable("C storage class in c++!"); } } if (SC == SC_Static && CurContext->isRecord()) { if (const CXXRecordDecl *RD = dyn_cast(DC)) { if (RD->isLocalClass()) Diag(D.getIdentifierLoc(), diag::err_static_data_member_not_allowed_in_local_class) << Name << RD->getDeclName(); // C++98 [class.union]p1: If a union contains a static data member, // the program is ill-formed. C++11 drops this restriction. if (RD->isUnion()) Diag(D.getIdentifierLoc(), getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_static_data_member_in_union : diag::ext_static_data_member_in_union) << Name; // We conservatively disallow static data members in anonymous structs. else if (!RD->getDeclName()) Diag(D.getIdentifierLoc(), diag::err_static_data_member_not_allowed_in_anon_struct) << Name << RD->isUnion(); } } // Match up the template parameter lists with the scope specifier, then // determine whether we have a template or a template specialization. TemplateParams = MatchTemplateParametersToScopeSpecifier( D.getDeclSpec().getLocStart(), D.getIdentifierLoc(), D.getCXXScopeSpec(), D.getName().getKind() == UnqualifiedId::IK_TemplateId ? D.getName().TemplateId : nullptr, TemplateParamLists, /*never a friend*/ false, IsMemberSpecialization, Invalid); if (TemplateParams) { if (!TemplateParams->size() && D.getName().getKind() != UnqualifiedId::IK_TemplateId) { // There is an extraneous 'template<>' for this variable. Complain // about it, but allow the declaration of the variable. Diag(TemplateParams->getTemplateLoc(), diag::err_template_variable_noparams) << II << SourceRange(TemplateParams->getTemplateLoc(), TemplateParams->getRAngleLoc()); TemplateParams = nullptr; } else { if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { // This is an explicit specialization or a partial specialization. // FIXME: Check that we can declare a specialization here. IsVariableTemplateSpecialization = true; IsPartialSpecialization = TemplateParams->size() > 0; } else { // if (TemplateParams->size() > 0) // This is a template declaration. IsVariableTemplate = true; // Check that we can declare a template here. if (CheckTemplateDeclScope(S, TemplateParams)) return nullptr; // Only C++1y supports variable templates (N3651). Diag(D.getIdentifierLoc(), getLangOpts().CPlusPlus14 ? diag::warn_cxx11_compat_variable_template : diag::ext_variable_template); } } } else { assert( (Invalid || D.getName().getKind() != UnqualifiedId::IK_TemplateId) && "should have a 'template<>' for this decl"); } if (IsVariableTemplateSpecialization) { SourceLocation TemplateKWLoc = TemplateParamLists.size() > 0 ? TemplateParamLists[0]->getTemplateLoc() : SourceLocation(); DeclResult Res = ActOnVarTemplateSpecialization( S, D, TInfo, TemplateKWLoc, TemplateParams, SC, IsPartialSpecialization); if (Res.isInvalid()) return nullptr; NewVD = cast(Res.get()); AddToScope = false; } else if (D.isDecompositionDeclarator()) { NewVD = DecompositionDecl::Create(Context, DC, D.getLocStart(), D.getIdentifierLoc(), R, TInfo, SC, Bindings); } else NewVD = VarDecl::Create(Context, DC, D.getLocStart(), D.getIdentifierLoc(), II, R, TInfo, SC); // If this is supposed to be a variable template, create it as such. if (IsVariableTemplate) { NewTemplate = VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name, TemplateParams, NewVD); NewVD->setDescribedVarTemplate(NewTemplate); } // If this decl has an auto type in need of deduction, make a note of the // Decl so we can diagnose uses of it in its own initializer. if (R->getContainedDeducedType()) ParsingInitForAutoVars.insert(NewVD); if (D.isInvalidType() || Invalid) { NewVD->setInvalidDecl(); if (NewTemplate) NewTemplate->setInvalidDecl(); } SetNestedNameSpecifier(NewVD, D); // If we have any template parameter lists that don't directly belong to // the variable (matching the scope specifier), store them. unsigned VDTemplateParamLists = TemplateParams ? 1 : 0; if (TemplateParamLists.size() > VDTemplateParamLists) NewVD->setTemplateParameterListsInfo( Context, TemplateParamLists.drop_back(VDTemplateParamLists)); if (D.getDeclSpec().isConstexprSpecified()) { NewVD->setConstexpr(true); // C++1z [dcl.spec.constexpr]p1: // A static data member declared with the constexpr specifier is // implicitly an inline variable. if (NewVD->isStaticDataMember() && getLangOpts().CPlusPlus1z) NewVD->setImplicitlyInline(); } if (D.getDeclSpec().isConceptSpecified()) { if (VarTemplateDecl *VTD = NewVD->getDescribedVarTemplate()) VTD->setConcept(); // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not // be declared with the thread_local, inline, friend, or constexpr // specifiers, [...] if (D.getDeclSpec().getThreadStorageClassSpec() == TSCS_thread_local) { Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), diag::err_concept_decl_invalid_specifiers) << 0 << 0; NewVD->setInvalidDecl(true); } if (D.getDeclSpec().isConstexprSpecified()) { Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_concept_decl_invalid_specifiers) << 0 << 3; NewVD->setInvalidDecl(true); } // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be // applied only to the definition of a function template or variable // template, declared in namespace scope. if (IsVariableTemplateSpecialization) { Diag(D.getDeclSpec().getConceptSpecLoc(), diag::err_concept_specified_specialization) << (IsPartialSpecialization ? 2 : 1); } // C++ Concepts TS [dcl.spec.concept]p6: A variable concept has the // following restrictions: // - The declared type shall have the type bool. if (!Context.hasSameType(NewVD->getType(), Context.BoolTy) && !NewVD->isInvalidDecl()) { Diag(D.getIdentifierLoc(), diag::err_variable_concept_bool_decl); NewVD->setInvalidDecl(true); } } } if (D.getDeclSpec().isInlineSpecified()) { if (!getLangOpts().CPlusPlus) { Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function) << 0; } else if (CurContext->isFunctionOrMethod()) { // 'inline' is not allowed on block scope variable declaration. Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_declaration_block_scope) << Name << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc()); } else { Diag(D.getDeclSpec().getInlineSpecLoc(), getLangOpts().CPlusPlus1z ? diag::warn_cxx14_compat_inline_variable : diag::ext_inline_variable); NewVD->setInlineSpecified(); } } // Set the lexical context. If the declarator has a C++ scope specifier, the // lexical context will be different from the semantic context. NewVD->setLexicalDeclContext(CurContext); if (NewTemplate) NewTemplate->setLexicalDeclContext(CurContext); if (IsLocalExternDecl) { if (D.isDecompositionDeclarator()) for (auto *B : Bindings) B->setLocalExternDecl(); else NewVD->setLocalExternDecl(); } bool EmitTLSUnsupportedError = false; if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) { // C++11 [dcl.stc]p4: // When thread_local is applied to a variable of block scope the // storage-class-specifier static is implied if it does not appear // explicitly. // Core issue: 'static' is not implied if the variable is declared // 'extern'. if (NewVD->hasLocalStorage() && (SCSpec != DeclSpec::SCS_unspecified || TSCS != DeclSpec::TSCS_thread_local || !DC->isFunctionOrMethod())) Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), diag::err_thread_non_global) << DeclSpec::getSpecifierName(TSCS); else if (!Context.getTargetInfo().isTLSSupported()) { if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice) { // Postpone error emission until we've collected attributes required to // figure out whether it's a host or device variable and whether the // error should be ignored. EmitTLSUnsupportedError = true; // We still need to mark the variable as TLS so it shows up in AST with // proper storage class for other tools to use even if we're not going // to emit any code for it. NewVD->setTSCSpec(TSCS); } else Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), diag::err_thread_unsupported); } else NewVD->setTSCSpec(TSCS); } // C99 6.7.4p3 // An inline definition of a function with external linkage shall // not contain a definition of a modifiable object with static or // thread storage duration... // We only apply this when the function is required to be defined // elsewhere, i.e. when the function is not 'extern inline'. Note // that a local variable with thread storage duration still has to // be marked 'static'. Also note that it's possible to get these // semantics in C++ using __attribute__((gnu_inline)). if (SC == SC_Static && S->getFnParent() != nullptr && !NewVD->getType().isConstQualified()) { FunctionDecl *CurFD = getCurFunctionDecl(); if (CurFD && isFunctionDefinitionDiscarded(*this, CurFD)) { Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::warn_static_local_in_extern_inline); MaybeSuggestAddingStaticToDecl(CurFD); } } if (D.getDeclSpec().isModulePrivateSpecified()) { if (IsVariableTemplateSpecialization) Diag(NewVD->getLocation(), diag::err_module_private_specialization) << (IsPartialSpecialization ? 1 : 0) << FixItHint::CreateRemoval( D.getDeclSpec().getModulePrivateSpecLoc()); else if (IsMemberSpecialization) Diag(NewVD->getLocation(), diag::err_module_private_specialization) << 2 << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); else if (NewVD->hasLocalStorage()) Diag(NewVD->getLocation(), diag::err_module_private_local) << 0 << NewVD->getDeclName() << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); else { NewVD->setModulePrivate(); if (NewTemplate) NewTemplate->setModulePrivate(); for (auto *B : Bindings) B->setModulePrivate(); } } // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewVD, D); if (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice) { if (EmitTLSUnsupportedError && ((getLangOpts().CUDA && DeclAttrsMatchCUDAMode(getLangOpts(), NewVD)) || (getLangOpts().OpenMPIsDevice && NewVD->hasAttr()))) Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), diag::err_thread_unsupported); // CUDA B.2.5: "__shared__ and __constant__ variables have implied static // storage [duration]." if (SC == SC_None && S->getFnParent() != nullptr && (NewVD->hasAttr() || NewVD->hasAttr())) { NewVD->setStorageClass(SC_Static); } } // Ensure that dllimport globals without explicit storage class are treated as // extern. The storage class is set above using parsed attributes. Now we can // check the VarDecl itself. assert(!NewVD->hasAttr() || NewVD->getAttr()->isInherited() || NewVD->isStaticDataMember() || NewVD->getStorageClass() != SC_None); // In auto-retain/release, infer strong retension for variables of // retainable type. if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewVD)) NewVD->setInvalidDecl(); // Handle GNU asm-label extension (encoded as an attribute). if (Expr *E = (Expr*)D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast(E); StringRef Label = SE->getString(); if (S->getFnParent() != nullptr) { switch (SC) { case SC_None: case SC_Auto: Diag(E->getExprLoc(), diag::warn_asm_label_on_auto_decl) << Label; break; case SC_Register: // Local Named register if (!Context.getTargetInfo().isValidGCCRegisterName(Label) && DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl())) Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label; break; case SC_Static: case SC_Extern: case SC_PrivateExtern: break; } } else if (SC == SC_Register) { // Global Named register if (DeclAttrsMatchCUDAMode(getLangOpts(), NewVD)) { const auto &TI = Context.getTargetInfo(); bool HasSizeMismatch; if (!TI.isValidGCCRegisterName(Label)) Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label; else if (!TI.validateGlobalRegisterVariable(Label, Context.getTypeSize(R), HasSizeMismatch)) Diag(E->getExprLoc(), diag::err_asm_invalid_global_var_reg) << Label; else if (HasSizeMismatch) Diag(E->getExprLoc(), diag::err_asm_register_size_mismatch) << Label; } if (!R->isIntegralType(Context) && !R->isPointerType()) { Diag(D.getLocStart(), diag::err_asm_bad_register_type); NewVD->setInvalidDecl(true); } } NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context, Label, 0)); } else if (!ExtnameUndeclaredIdentifiers.empty()) { llvm::DenseMap::iterator I = ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier()); if (I != ExtnameUndeclaredIdentifiers.end()) { if (isDeclExternC(NewVD)) { NewVD->addAttr(I->second); ExtnameUndeclaredIdentifiers.erase(I); } else Diag(NewVD->getLocation(), diag::warn_redefine_extname_not_applied) << /*Variable*/1 << NewVD; } } // Find the shadowed declaration before filtering for scope. NamedDecl *ShadowedDecl = D.getCXXScopeSpec().isEmpty() ? getShadowedDeclaration(NewVD, Previous) : nullptr; // Don't consider existing declarations that are in a different // scope and are out-of-semantic-context declarations (if the new // declaration has linkage). FilterLookupForScope(Previous, OriginalDC, S, shouldConsiderLinkage(NewVD), D.getCXXScopeSpec().isNotEmpty() || IsMemberSpecialization || IsVariableTemplateSpecialization); // Check whether the previous declaration is in the same block scope. This // affects whether we merge types with it, per C++11 [dcl.array]p3. if (getLangOpts().CPlusPlus && NewVD->isLocalVarDecl() && NewVD->hasExternalStorage()) NewVD->setPreviousDeclInSameBlockScope( Previous.isSingleResult() && !Previous.isShadowed() && isDeclInScope(Previous.getFoundDecl(), OriginalDC, S, false)); if (!getLangOpts().CPlusPlus) { D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); } else { // If this is an explicit specialization of a static data member, check it. if (IsMemberSpecialization && !NewVD->isInvalidDecl() && CheckMemberSpecialization(NewVD, Previous)) NewVD->setInvalidDecl(); // Merge the decl with the existing one if appropriate. if (!Previous.empty()) { if (Previous.isSingleResult() && isa(Previous.getFoundDecl()) && D.getCXXScopeSpec().isSet()) { // The user tried to define a non-static data member // out-of-line (C++ [dcl.meaning]p1). Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line) << D.getCXXScopeSpec().getRange(); Previous.clear(); NewVD->setInvalidDecl(); } } else if (D.getCXXScopeSpec().isSet()) { // No previous declaration in the qualifying scope. Diag(D.getIdentifierLoc(), diag::err_no_member) << Name << computeDeclContext(D.getCXXScopeSpec(), true) << D.getCXXScopeSpec().getRange(); NewVD->setInvalidDecl(); } if (!IsVariableTemplateSpecialization) D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare [...] // an explicit specialization (14.8.3) or a partial specialization of a // concept definition. if (IsVariableTemplateSpecialization && !D.getDeclSpec().isConceptSpecified() && !Previous.empty() && Previous.isSingleResult()) { NamedDecl *PreviousDecl = Previous.getFoundDecl(); if (VarTemplateDecl *VarTmpl = dyn_cast(PreviousDecl)) { if (VarTmpl->isConcept()) { Diag(NewVD->getLocation(), diag::err_concept_specialized) << 1 /*variable*/ << (IsPartialSpecialization ? 2 /*partially specialized*/ : 1 /*explicitly specialized*/); Diag(VarTmpl->getLocation(), diag::note_previous_declaration); NewVD->setInvalidDecl(); } } } if (NewTemplate) { VarTemplateDecl *PrevVarTemplate = NewVD->getPreviousDecl() ? NewVD->getPreviousDecl()->getDescribedVarTemplate() : nullptr; // Check the template parameter list of this declaration, possibly // merging in the template parameter list from the previous variable // template declaration. if (CheckTemplateParameterList( TemplateParams, PrevVarTemplate ? PrevVarTemplate->getTemplateParameters() : nullptr, (D.getCXXScopeSpec().isSet() && DC && DC->isRecord() && DC->isDependentContext()) ? TPC_ClassTemplateMember : TPC_VarTemplate)) NewVD->setInvalidDecl(); // If we are providing an explicit specialization of a static variable // template, make a note of that. if (PrevVarTemplate && PrevVarTemplate->getInstantiatedFromMemberTemplate()) PrevVarTemplate->setMemberSpecialization(); } } // Diagnose shadowed variables iff this isn't a redeclaration. if (ShadowedDecl && !D.isRedeclaration()) CheckShadow(NewVD, ShadowedDecl, Previous); ProcessPragmaWeak(S, NewVD); // If this is the first declaration of an extern C variable, update // the map of such variables. if (NewVD->isFirstDecl() && !NewVD->isInvalidDecl() && isIncompleteDeclExternC(*this, NewVD)) RegisterLocallyScopedExternCDecl(NewVD, S); if (getLangOpts().CPlusPlus && NewVD->isStaticLocal()) { Decl *ManglingContextDecl; if (MangleNumberingContext *MCtx = getCurrentMangleNumberContext( NewVD->getDeclContext(), ManglingContextDecl)) { Context.setManglingNumber( NewVD, MCtx->getManglingNumber( NewVD, getMSManglingNumber(getLangOpts(), S))); Context.setStaticLocalNumber(NewVD, MCtx->getStaticLocalNumber(NewVD)); } } // Special handling of variable named 'main'. if (Name.getAsIdentifierInfo() && Name.getAsIdentifierInfo()->isStr("main") && NewVD->getDeclContext()->getRedeclContext()->isTranslationUnit() && !getLangOpts().Freestanding && !NewVD->getDescribedVarTemplate()) { // C++ [basic.start.main]p3 // A program that declares a variable main at global scope is ill-formed. if (getLangOpts().CPlusPlus) Diag(D.getLocStart(), diag::err_main_global_variable); // In C, and external-linkage variable named main results in undefined // behavior. else if (NewVD->hasExternalFormalLinkage()) Diag(D.getLocStart(), diag::warn_main_redefined); } if (D.isRedeclaration() && !Previous.empty()) { checkDLLAttributeRedeclaration( *this, dyn_cast(Previous.getRepresentativeDecl()), NewVD, IsMemberSpecialization, D.isFunctionDefinition()); } if (NewTemplate) { if (NewVD->isInvalidDecl()) NewTemplate->setInvalidDecl(); ActOnDocumentableDecl(NewTemplate); return NewTemplate; } if (IsMemberSpecialization && !NewVD->isInvalidDecl()) CompleteMemberSpecialization(NewVD, Previous); return NewVD; } /// Enum describing the %select options in diag::warn_decl_shadow. enum ShadowedDeclKind { SDK_Local, SDK_Global, SDK_StaticMember, SDK_Field, SDK_Typedef, SDK_Using }; /// Determine what kind of declaration we're shadowing. static ShadowedDeclKind computeShadowedDeclKind(const NamedDecl *ShadowedDecl, const DeclContext *OldDC) { if (isa(ShadowedDecl)) return SDK_Using; else if (isa(ShadowedDecl)) return SDK_Typedef; else if (isa(OldDC)) return isa(ShadowedDecl) ? SDK_Field : SDK_StaticMember; return OldDC->isFileContext() ? SDK_Global : SDK_Local; } /// Return the location of the capture if the given lambda captures the given /// variable \p VD, or an invalid source location otherwise. static SourceLocation getCaptureLocation(const LambdaScopeInfo *LSI, const VarDecl *VD) { for (const LambdaScopeInfo::Capture &Capture : LSI->Captures) { if (Capture.isVariableCapture() && Capture.getVariable() == VD) return Capture.getLocation(); } return SourceLocation(); } static bool shouldWarnIfShadowedDecl(const DiagnosticsEngine &Diags, const LookupResult &R) { // Only diagnose if we're shadowing an unambiguous field or variable. if (R.getResultKind() != LookupResult::Found) return false; // Return false if warning is ignored. return !Diags.isIgnored(diag::warn_decl_shadow, R.getNameLoc()); } /// \brief Return the declaration shadowed by the given variable \p D, or null /// if it doesn't shadow any declaration or shadowing warnings are disabled. NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D, const LookupResult &R) { if (!shouldWarnIfShadowedDecl(Diags, R)) return nullptr; // Don't diagnose declarations at file scope. if (D->hasGlobalStorage()) return nullptr; NamedDecl *ShadowedDecl = R.getFoundDecl(); return isa(ShadowedDecl) || isa(ShadowedDecl) ? ShadowedDecl : nullptr; } /// \brief Return the declaration shadowed by the given typedef \p D, or null /// if it doesn't shadow any declaration or shadowing warnings are disabled. NamedDecl *Sema::getShadowedDeclaration(const TypedefNameDecl *D, const LookupResult &R) { // Don't warn if typedef declaration is part of a class if (D->getDeclContext()->isRecord()) return nullptr; if (!shouldWarnIfShadowedDecl(Diags, R)) return nullptr; NamedDecl *ShadowedDecl = R.getFoundDecl(); return isa(ShadowedDecl) ? ShadowedDecl : nullptr; } /// \brief Diagnose variable or built-in function shadowing. Implements /// -Wshadow. /// /// This method is called whenever a VarDecl is added to a "useful" /// scope. /// /// \param ShadowedDecl the declaration that is shadowed by the given variable /// \param R the lookup of the name /// void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, const LookupResult &R) { DeclContext *NewDC = D->getDeclContext(); if (FieldDecl *FD = dyn_cast(ShadowedDecl)) { // Fields are not shadowed by variables in C++ static methods. if (CXXMethodDecl *MD = dyn_cast(NewDC)) if (MD->isStatic()) return; // Fields shadowed by constructor parameters are a special case. Usually // the constructor initializes the field with the parameter. if (isa(NewDC)) if (const auto PVD = dyn_cast(D)) { // Remember that this was shadowed so we can either warn about its // modification or its existence depending on warning settings. ShadowingDecls.insert({PVD->getCanonicalDecl(), FD}); return; } } if (VarDecl *shadowedVar = dyn_cast(ShadowedDecl)) if (shadowedVar->isExternC()) { // For shadowing external vars, make sure that we point to the global // declaration, not a locally scoped extern declaration. for (auto I : shadowedVar->redecls()) if (I->isFileVarDecl()) { ShadowedDecl = I; break; } } DeclContext *OldDC = ShadowedDecl->getDeclContext()->getRedeclContext(); unsigned WarningDiag = diag::warn_decl_shadow; SourceLocation CaptureLoc; if (isa(D) && isa(ShadowedDecl) && NewDC && isa(NewDC)) { if (const auto *RD = dyn_cast(NewDC->getParent())) { if (RD->isLambda() && OldDC->Encloses(NewDC->getLexicalParent())) { if (RD->getLambdaCaptureDefault() == LCD_None) { // Try to avoid warnings for lambdas with an explicit capture list. const auto *LSI = cast(getCurFunction()); // Warn only when the lambda captures the shadowed decl explicitly. CaptureLoc = getCaptureLocation(LSI, cast(ShadowedDecl)); if (CaptureLoc.isInvalid()) WarningDiag = diag::warn_decl_shadow_uncaptured_local; } else { // Remember that this was shadowed so we can avoid the warning if the // shadowed decl isn't captured and the warning settings allow it. cast(getCurFunction()) ->ShadowingDecls.push_back( {cast(D), cast(ShadowedDecl)}); return; } } if (cast(ShadowedDecl)->hasLocalStorage()) { // A variable can't shadow a local variable in an enclosing scope, if // they are separated by a non-capturing declaration context. for (DeclContext *ParentDC = NewDC; ParentDC && !ParentDC->Equals(OldDC); ParentDC = getLambdaAwareParentOfDeclContext(ParentDC)) { // Only block literals, captured statements, and lambda expressions // can capture; other scopes don't. if (!isa(ParentDC) && !isa(ParentDC) && !isLambdaCallOperator(ParentDC)) { return; } } } } } // Only warn about certain kinds of shadowing for class members. if (NewDC && NewDC->isRecord()) { // In particular, don't warn about shadowing non-class members. if (!OldDC->isRecord()) return; // TODO: should we warn about static data members shadowing // static data members from base classes? // TODO: don't diagnose for inaccessible shadowed members. // This is hard to do perfectly because we might friend the // shadowing context, but that's just a false negative. } DeclarationName Name = R.getLookupName(); // Emit warning and note. if (getSourceManager().isInSystemMacro(R.getNameLoc())) return; ShadowedDeclKind Kind = computeShadowedDeclKind(ShadowedDecl, OldDC); Diag(R.getNameLoc(), WarningDiag) << Name << Kind << OldDC; if (!CaptureLoc.isInvalid()) Diag(CaptureLoc, diag::note_var_explicitly_captured_here) << Name << /*explicitly*/ 1; Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration); } /// Diagnose shadowing for variables shadowed in the lambda record \p LambdaRD /// when these variables are captured by the lambda. void Sema::DiagnoseShadowingLambdaDecls(const LambdaScopeInfo *LSI) { for (const auto &Shadow : LSI->ShadowingDecls) { const VarDecl *ShadowedDecl = Shadow.ShadowedDecl; // Try to avoid the warning when the shadowed decl isn't captured. SourceLocation CaptureLoc = getCaptureLocation(LSI, ShadowedDecl); const DeclContext *OldDC = ShadowedDecl->getDeclContext(); Diag(Shadow.VD->getLocation(), CaptureLoc.isInvalid() ? diag::warn_decl_shadow_uncaptured_local : diag::warn_decl_shadow) << Shadow.VD->getDeclName() << computeShadowedDeclKind(ShadowedDecl, OldDC) << OldDC; if (!CaptureLoc.isInvalid()) Diag(CaptureLoc, diag::note_var_explicitly_captured_here) << Shadow.VD->getDeclName() << /*explicitly*/ 0; Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration); } } /// \brief Check -Wshadow without the advantage of a previous lookup. void Sema::CheckShadow(Scope *S, VarDecl *D) { if (Diags.isIgnored(diag::warn_decl_shadow, D->getLocation())) return; LookupResult R(*this, D->getDeclName(), D->getLocation(), Sema::LookupOrdinaryName, Sema::ForRedeclaration); LookupName(R, S); if (NamedDecl *ShadowedDecl = getShadowedDeclaration(D, R)) CheckShadow(D, ShadowedDecl, R); } /// Check if 'E', which is an expression that is about to be modified, refers /// to a constructor parameter that shadows a field. void Sema::CheckShadowingDeclModification(Expr *E, SourceLocation Loc) { // Quickly ignore expressions that can't be shadowing ctor parameters. if (!getLangOpts().CPlusPlus || ShadowingDecls.empty()) return; E = E->IgnoreParenImpCasts(); auto *DRE = dyn_cast(E); if (!DRE) return; const NamedDecl *D = cast(DRE->getDecl()->getCanonicalDecl()); auto I = ShadowingDecls.find(D); if (I == ShadowingDecls.end()) return; const NamedDecl *ShadowedDecl = I->second; const DeclContext *OldDC = ShadowedDecl->getDeclContext(); Diag(Loc, diag::warn_modifying_shadowing_decl) << D << OldDC; Diag(D->getLocation(), diag::note_var_declared_here) << D; Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration); // Avoid issuing multiple warnings about the same decl. ShadowingDecls.erase(I); } /// Check for conflict between this global or extern "C" declaration and /// previous global or extern "C" declarations. This is only used in C++. template static bool checkGlobalOrExternCConflict( Sema &S, const T *ND, bool IsGlobal, LookupResult &Previous) { assert(S.getLangOpts().CPlusPlus && "only C++ has extern \"C\""); NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName()); if (!Prev && IsGlobal && !isIncompleteDeclExternC(S, ND)) { // The common case: this global doesn't conflict with any extern "C" // declaration. return false; } if (Prev) { if (!IsGlobal || isIncompleteDeclExternC(S, ND)) { // Both the old and new declarations have C language linkage. This is a // redeclaration. Previous.clear(); Previous.addDecl(Prev); return true; } // This is a global, non-extern "C" declaration, and there is a previous // non-global extern "C" declaration. Diagnose if this is a variable // declaration. if (!isa(ND)) return false; } else { // The declaration is extern "C". Check for any declaration in the // translation unit which might conflict. if (IsGlobal) { // We have already performed the lookup into the translation unit. IsGlobal = false; for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); I != E; ++I) { if (isa(*I)) { Prev = *I; break; } } } else { DeclContext::lookup_result R = S.Context.getTranslationUnitDecl()->lookup(ND->getDeclName()); for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end(); I != E; ++I) { if (isa(*I)) { Prev = *I; break; } // FIXME: If we have any other entity with this name in global scope, // the declaration is ill-formed, but that is a defect: it breaks the // 'stat' hack, for instance. Only variables can have mangled name // clashes with extern "C" declarations, so only they deserve a // diagnostic. } } if (!Prev) return false; } // Use the first declaration's location to ensure we point at something which // is lexically inside an extern "C" linkage-spec. assert(Prev && "should have found a previous declaration to diagnose"); if (FunctionDecl *FD = dyn_cast(Prev)) Prev = FD->getFirstDecl(); else Prev = cast(Prev)->getFirstDecl(); S.Diag(ND->getLocation(), diag::err_extern_c_global_conflict) << IsGlobal << ND; S.Diag(Prev->getLocation(), diag::note_extern_c_global_conflict) << IsGlobal; return false; } /// Apply special rules for handling extern "C" declarations. Returns \c true /// if we have found that this is a redeclaration of some prior entity. /// /// Per C++ [dcl.link]p6: /// Two declarations [for a function or variable] with C language linkage /// with the same name that appear in different scopes refer to the same /// [entity]. An entity with C language linkage shall not be declared with /// the same name as an entity in global scope. template static bool checkForConflictWithNonVisibleExternC(Sema &S, const T *ND, LookupResult &Previous) { if (!S.getLangOpts().CPlusPlus) { // In C, when declaring a global variable, look for a corresponding 'extern' // variable declared in function scope. We don't need this in C++, because // we find local extern decls in the surrounding file-scope DeclContext. if (ND->getDeclContext()->getRedeclContext()->isTranslationUnit()) { if (NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName())) { Previous.clear(); Previous.addDecl(Prev); return true; } } return false; } // A declaration in the translation unit can conflict with an extern "C" // declaration. if (ND->getDeclContext()->getRedeclContext()->isTranslationUnit()) return checkGlobalOrExternCConflict(S, ND, /*IsGlobal*/true, Previous); // An extern "C" declaration can conflict with a declaration in the // translation unit or can be a redeclaration of an extern "C" declaration // in another scope. if (isIncompleteDeclExternC(S,ND)) return checkGlobalOrExternCConflict(S, ND, /*IsGlobal*/false, Previous); // Neither global nor extern "C": nothing to do. return false; } void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { // If the decl is already known invalid, don't check it. if (NewVD->isInvalidDecl()) return; TypeSourceInfo *TInfo = NewVD->getTypeSourceInfo(); QualType T = TInfo->getType(); // Defer checking an 'auto' type until its initializer is attached. if (T->isUndeducedType()) return; if (NewVD->hasAttrs()) CheckAlignasUnderalignment(NewVD); if (T->isObjCObjectType()) { Diag(NewVD->getLocation(), diag::err_statically_allocated_object) << FixItHint::CreateInsertion(NewVD->getLocation(), "*"); T = Context.getObjCObjectPointerType(T); NewVD->setType(T); } // Emit an error if an address space was applied to decl with local storage. // This includes arrays of objects with address space qualifiers, but not // automatic variables that point to other address spaces. // ISO/IEC TR 18037 S5.1.2 if (!getLangOpts().OpenCL && NewVD->hasLocalStorage() && T.getAddressSpace() != 0) { Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 0; NewVD->setInvalidDecl(); return; } // OpenCL v1.2 s6.8 - The static qualifier is valid only in program // scope. if (getLangOpts().OpenCLVersion == 120 && !getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers") && NewVD->isStaticLocal()) { Diag(NewVD->getLocation(), diag::err_static_function_scope); NewVD->setInvalidDecl(); return; } if (getLangOpts().OpenCL) { // OpenCL v2.0 s6.12.5 - The __block storage type is not supported. if (NewVD->hasAttr()) { Diag(NewVD->getLocation(), diag::err_opencl_block_storage_type); return; } if (T->isBlockPointerType()) { // OpenCL v2.0 s6.12.5 - Any block declaration must be const qualified and // can't use 'extern' storage class. if (!T.isConstQualified()) { Diag(NewVD->getLocation(), diag::err_opencl_invalid_block_declaration) << 0 /*const*/; NewVD->setInvalidDecl(); return; } if (NewVD->hasExternalStorage()) { Diag(NewVD->getLocation(), diag::err_opencl_extern_block_declaration); NewVD->setInvalidDecl(); return; } } // OpenCL v1.2 s6.5 - All program scope variables must be declared in the // __constant address space. // OpenCL v2.0 s6.5.1 - Variables defined at program scope and static // variables inside a function can also be declared in the global // address space. if (NewVD->isFileVarDecl() || NewVD->isStaticLocal() || NewVD->hasExternalStorage()) { if (!T->isSamplerT() && !(T.getAddressSpace() == LangAS::opencl_constant || (T.getAddressSpace() == LangAS::opencl_global && getLangOpts().OpenCLVersion == 200))) { int Scope = NewVD->isStaticLocal() | NewVD->hasExternalStorage() << 1; if (getLangOpts().OpenCLVersion == 200) Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space) << Scope << "global or constant"; else Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space) << Scope << "constant"; NewVD->setInvalidDecl(); return; } } else { if (T.getAddressSpace() == LangAS::opencl_global) { Diag(NewVD->getLocation(), diag::err_opencl_function_variable) << 1 /*is any function*/ << "global"; NewVD->setInvalidDecl(); return; } if (T.getAddressSpace() == LangAS::opencl_constant || T.getAddressSpace() == LangAS::opencl_local) { FunctionDecl *FD = getCurFunctionDecl(); // OpenCL v1.1 s6.5.2 and s6.5.3: no local or constant variables // in functions. if (FD && !FD->hasAttr()) { if (T.getAddressSpace() == LangAS::opencl_constant) Diag(NewVD->getLocation(), diag::err_opencl_function_variable) << 0 /*non-kernel only*/ << "constant"; else Diag(NewVD->getLocation(), diag::err_opencl_function_variable) << 0 /*non-kernel only*/ << "local"; NewVD->setInvalidDecl(); return; } // OpenCL v2.0 s6.5.2 and s6.5.3: local and constant variables must be // in the outermost scope of a kernel function. if (FD && FD->hasAttr()) { if (!getCurScope()->isFunctionScope()) { if (T.getAddressSpace() == LangAS::opencl_constant) Diag(NewVD->getLocation(), diag::err_opencl_addrspace_scope) << "constant"; else Diag(NewVD->getLocation(), diag::err_opencl_addrspace_scope) << "local"; NewVD->setInvalidDecl(); return; } } } else if (T.getAddressSpace() != LangAS::Default) { // Do not allow other address spaces on automatic variable. Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 1; NewVD->setInvalidDecl(); return; } } } if (NewVD->hasLocalStorage() && T.isObjCGCWeak() && !NewVD->hasAttr()) { if (getLangOpts().getGC() != LangOptions::NonGC) Diag(NewVD->getLocation(), diag::warn_gc_attribute_weak_on_local); else { assert(!getLangOpts().ObjCAutoRefCount); Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local); } } bool isVM = T->isVariablyModifiedType(); if (isVM || NewVD->hasAttr() || NewVD->hasAttr()) getCurFunction()->setHasBranchProtectedScope(); if ((isVM && NewVD->hasLinkage()) || (T->isVariableArrayType() && NewVD->hasGlobalStorage())) { bool SizeIsNegative; llvm::APSInt Oversized; TypeSourceInfo *FixedTInfo = TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context, SizeIsNegative, Oversized); if (!FixedTInfo && T->isVariableArrayType()) { const VariableArrayType *VAT = Context.getAsVariableArrayType(T); // FIXME: This won't give the correct result for // int a[10][n]; SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange(); if (NewVD->isFileVarDecl()) Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope) << SizeRange; else if (NewVD->isStaticLocal()) Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage) << SizeRange; else Diag(NewVD->getLocation(), diag::err_vla_decl_has_extern_linkage) << SizeRange; NewVD->setInvalidDecl(); return; } if (!FixedTInfo) { if (NewVD->isFileVarDecl()) Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope); else Diag(NewVD->getLocation(), diag::err_vm_decl_has_extern_linkage); NewVD->setInvalidDecl(); return; } Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size); NewVD->setType(FixedTInfo->getType()); NewVD->setTypeSourceInfo(FixedTInfo); } if (T->isVoidType()) { // C++98 [dcl.stc]p5: The extern specifier can be applied only to the names // of objects and functions. if (NewVD->isThisDeclarationADefinition() || getLangOpts().CPlusPlus) { Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type) << T; NewVD->setInvalidDecl(); return; } } if (!NewVD->hasLocalStorage() && NewVD->hasAttr()) { Diag(NewVD->getLocation(), diag::err_block_on_nonlocal); NewVD->setInvalidDecl(); return; } if (isVM && NewVD->hasAttr()) { Diag(NewVD->getLocation(), diag::err_block_on_vm); NewVD->setInvalidDecl(); return; } if (NewVD->isConstexpr() && !T->isDependentType() && RequireLiteralType(NewVD->getLocation(), T, diag::err_constexpr_var_non_literal)) { NewVD->setInvalidDecl(); return; } } /// \brief Perform semantic checking on a newly-created variable /// declaration. /// /// This routine performs all of the type-checking required for a /// variable declaration once it has been built. It is used both to /// check variables after they have been parsed and their declarators /// have been translated into a declaration, and to check variables /// that have been instantiated from a template. /// /// Sets NewVD->isInvalidDecl() if an error was encountered. /// /// Returns true if the variable declaration is a redeclaration. bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) { CheckVariableDeclarationType(NewVD); // If the decl is already known invalid, don't check it. if (NewVD->isInvalidDecl()) return false; // If we did not find anything by this name, look for a non-visible // extern "C" declaration with the same name. if (Previous.empty() && checkForConflictWithNonVisibleExternC(*this, NewVD, Previous)) Previous.setShadowed(); if (!Previous.empty()) { MergeVarDecl(NewVD, Previous); return true; } return false; } namespace { struct FindOverriddenMethod { Sema *S; CXXMethodDecl *Method; /// Member lookup function that determines whether a given C++ /// method overrides a method in a base class, to be used with /// CXXRecordDecl::lookupInBases(). bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { RecordDecl *BaseRecord = Specifier->getType()->getAs()->getDecl(); DeclarationName Name = Method->getDeclName(); // FIXME: Do we care about other names here too? if (Name.getNameKind() == DeclarationName::CXXDestructorName) { // We really want to find the base class destructor here. QualType T = S->Context.getTypeDeclType(BaseRecord); CanQualType CT = S->Context.getCanonicalType(T); Name = S->Context.DeclarationNames.getCXXDestructorName(CT); } for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); Path.Decls = Path.Decls.slice(1)) { NamedDecl *D = Path.Decls.front(); if (CXXMethodDecl *MD = dyn_cast(D)) { if (MD->isVirtual() && !S->IsOverload(Method, MD, false)) return true; } } return false; } }; enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted }; } // end anonymous namespace /// \brief Report an error regarding overriding, along with any relevant /// overriden methods. /// /// \param DiagID the primary error to report. /// \param MD the overriding method. /// \param OEK which overrides to include as notes. static void ReportOverrides(Sema& S, unsigned DiagID, const CXXMethodDecl *MD, OverrideErrorKind OEK = OEK_All) { S.Diag(MD->getLocation(), DiagID) << MD->getDeclName(); for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), E = MD->end_overridden_methods(); I != E; ++I) { // This check (& the OEK parameter) could be replaced by a predicate, but // without lambdas that would be overkill. This is still nicer than writing // out the diag loop 3 times. if ((OEK == OEK_All) || (OEK == OEK_NonDeleted && !(*I)->isDeleted()) || (OEK == OEK_Deleted && (*I)->isDeleted())) S.Diag((*I)->getLocation(), diag::note_overridden_virtual_function); } } /// AddOverriddenMethods - See if a method overrides any in the base classes, /// and if so, check that it's a valid override and remember it. bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { // Look for methods in base classes that this method might override. CXXBasePaths Paths; FindOverriddenMethod FOM; FOM.Method = MD; FOM.S = this; bool hasDeletedOverridenMethods = false; bool hasNonDeletedOverridenMethods = false; bool AddedAny = false; if (DC->lookupInBases(FOM, Paths)) { for (auto *I : Paths.found_decls()) { if (CXXMethodDecl *OldMD = dyn_cast(I)) { MD->addOverriddenMethod(OldMD->getCanonicalDecl()); if (!CheckOverridingFunctionReturnType(MD, OldMD) && !CheckOverridingFunctionAttributes(MD, OldMD) && !CheckOverridingFunctionExceptionSpec(MD, OldMD) && !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) { hasDeletedOverridenMethods |= OldMD->isDeleted(); hasNonDeletedOverridenMethods |= !OldMD->isDeleted(); AddedAny = true; } } } } if (hasDeletedOverridenMethods && !MD->isDeleted()) { ReportOverrides(*this, diag::err_non_deleted_override, MD, OEK_Deleted); } if (hasNonDeletedOverridenMethods && MD->isDeleted()) { ReportOverrides(*this, diag::err_deleted_override, MD, OEK_NonDeleted); } return AddedAny; } namespace { // Struct for holding all of the extra arguments needed by // DiagnoseInvalidRedeclaration to call Sema::ActOnFunctionDeclarator. struct ActOnFDArgs { Scope *S; Declarator &D; MultiTemplateParamsArg TemplateParamLists; bool AddToScope; }; } // end anonymous namespace namespace { // Callback to only accept typo corrections that have a non-zero edit distance. // Also only accept corrections that have the same parent decl. class DifferentNameValidatorCCC : public CorrectionCandidateCallback { public: DifferentNameValidatorCCC(ASTContext &Context, FunctionDecl *TypoFD, CXXRecordDecl *Parent) : Context(Context), OriginalFD(TypoFD), ExpectedParent(Parent ? Parent->getCanonicalDecl() : nullptr) {} bool ValidateCandidate(const TypoCorrection &candidate) override { if (candidate.getEditDistance() == 0) return false; SmallVector MismatchedParams; for (TypoCorrection::const_decl_iterator CDecl = candidate.begin(), CDeclEnd = candidate.end(); CDecl != CDeclEnd; ++CDecl) { FunctionDecl *FD = dyn_cast(*CDecl); if (FD && !FD->hasBody() && hasSimilarParameters(Context, FD, OriginalFD, MismatchedParams)) { if (CXXMethodDecl *MD = dyn_cast(FD)) { CXXRecordDecl *Parent = MD->getParent(); if (Parent && Parent->getCanonicalDecl() == ExpectedParent) return true; } else if (!ExpectedParent) { return true; } } } return false; } private: ASTContext &Context; FunctionDecl *OriginalFD; CXXRecordDecl *ExpectedParent; }; } // end anonymous namespace void Sema::MarkTypoCorrectedFunctionDefinition(const NamedDecl *F) { TypoCorrectedFunctionDefinitions.insert(F); } /// \brief Generate diagnostics for an invalid function redeclaration. /// /// This routine handles generating the diagnostic messages for an invalid /// function redeclaration, including finding possible similar declarations /// or performing typo correction if there are no previous declarations with /// the same name. /// /// Returns a NamedDecl iff typo correction was performed and substituting in /// the new declaration name does not cause new errors. static NamedDecl *DiagnoseInvalidRedeclaration( Sema &SemaRef, LookupResult &Previous, FunctionDecl *NewFD, ActOnFDArgs &ExtraArgs, bool IsLocalFriend, Scope *S) { DeclarationName Name = NewFD->getDeclName(); DeclContext *NewDC = NewFD->getDeclContext(); SmallVector MismatchedParams; SmallVector, 1> NearMatches; TypoCorrection Correction; bool IsDefinition = ExtraArgs.D.isFunctionDefinition(); unsigned DiagMsg = IsLocalFriend ? diag::err_no_matching_local_friend : diag::err_member_decl_does_not_match; LookupResult Prev(SemaRef, Name, NewFD->getLocation(), IsLocalFriend ? Sema::LookupLocalFriendName : Sema::LookupOrdinaryName, Sema::ForRedeclaration); NewFD->setInvalidDecl(); if (IsLocalFriend) SemaRef.LookupName(Prev, S); else SemaRef.LookupQualifiedName(Prev, NewDC); assert(!Prev.isAmbiguous() && "Cannot have an ambiguity in previous-declaration lookup"); CXXMethodDecl *MD = dyn_cast(NewFD); if (!Prev.empty()) { for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end(); Func != FuncEnd; ++Func) { FunctionDecl *FD = dyn_cast(*Func); if (FD && hasSimilarParameters(SemaRef.Context, FD, NewFD, MismatchedParams)) { // Add 1 to the index so that 0 can mean the mismatch didn't // involve a parameter unsigned ParamNum = MismatchedParams.empty() ? 0 : MismatchedParams.front() + 1; NearMatches.push_back(std::make_pair(FD, ParamNum)); } } // If the qualified name lookup yielded nothing, try typo correction } else if ((Correction = SemaRef.CorrectTypo( Prev.getLookupNameInfo(), Prev.getLookupKind(), S, &ExtraArgs.D.getCXXScopeSpec(), llvm::make_unique( SemaRef.Context, NewFD, MD ? MD->getParent() : nullptr), Sema::CTK_ErrorRecovery, IsLocalFriend ? nullptr : NewDC))) { // Set up everything for the call to ActOnFunctionDeclarator ExtraArgs.D.SetIdentifier(Correction.getCorrectionAsIdentifierInfo(), ExtraArgs.D.getIdentifierLoc()); Previous.clear(); Previous.setLookupName(Correction.getCorrection()); for (TypoCorrection::decl_iterator CDecl = Correction.begin(), CDeclEnd = Correction.end(); CDecl != CDeclEnd; ++CDecl) { FunctionDecl *FD = dyn_cast(*CDecl); if (FD && !FD->hasBody() && hasSimilarParameters(SemaRef.Context, FD, NewFD, MismatchedParams)) { Previous.addDecl(FD); } } bool wasRedeclaration = ExtraArgs.D.isRedeclaration(); NamedDecl *Result; // Retry building the function declaration with the new previous // declarations, and with errors suppressed. { // Trap errors. Sema::SFINAETrap Trap(SemaRef); // TODO: Refactor ActOnFunctionDeclarator so that we can call only the // pieces need to verify the typo-corrected C++ declaration and hopefully // eliminate the need for the parameter pack ExtraArgs. Result = SemaRef.ActOnFunctionDeclarator( ExtraArgs.S, ExtraArgs.D, Correction.getCorrectionDecl()->getDeclContext(), NewFD->getTypeSourceInfo(), Previous, ExtraArgs.TemplateParamLists, ExtraArgs.AddToScope); if (Trap.hasErrorOccurred()) Result = nullptr; } if (Result) { // Determine which correction we picked. Decl *Canonical = Result->getCanonicalDecl(); for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); I != E; ++I) if ((*I)->getCanonicalDecl() == Canonical) Correction.setCorrectionDecl(*I); // Let Sema know about the correction. SemaRef.MarkTypoCorrectedFunctionDefinition(Result); SemaRef.diagnoseTypo( Correction, SemaRef.PDiag(IsLocalFriend ? diag::err_no_matching_local_friend_suggest : diag::err_member_decl_does_not_match_suggest) << Name << NewDC << IsDefinition); return Result; } // Pretend the typo correction never occurred ExtraArgs.D.SetIdentifier(Name.getAsIdentifierInfo(), ExtraArgs.D.getIdentifierLoc()); ExtraArgs.D.setRedeclaration(wasRedeclaration); Previous.clear(); Previous.setLookupName(Name); } SemaRef.Diag(NewFD->getLocation(), DiagMsg) << Name << NewDC << IsDefinition << NewFD->getLocation(); bool NewFDisConst = false; if (CXXMethodDecl *NewMD = dyn_cast(NewFD)) NewFDisConst = NewMD->isConst(); for (SmallVectorImpl >::iterator NearMatch = NearMatches.begin(), NearMatchEnd = NearMatches.end(); NearMatch != NearMatchEnd; ++NearMatch) { FunctionDecl *FD = NearMatch->first; CXXMethodDecl *MD = dyn_cast(FD); bool FDisConst = MD && MD->isConst(); bool IsMember = MD || !IsLocalFriend; // FIXME: These notes are poorly worded for the local friend case. if (unsigned Idx = NearMatch->second) { ParmVarDecl *FDParam = FD->getParamDecl(Idx-1); SourceLocation Loc = FDParam->getTypeSpecStartLoc(); if (Loc.isInvalid()) Loc = FD->getLocation(); SemaRef.Diag(Loc, IsMember ? diag::note_member_def_close_param_match : diag::note_local_decl_close_param_match) << Idx << FDParam->getType() << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) << NewFDisConst << FD->getSourceRange().getEnd(); } else SemaRef.Diag(FD->getLocation(), IsMember ? diag::note_member_def_close_match : diag::note_local_decl_close_match); } return nullptr; } static StorageClass getFunctionStorageClass(Sema &SemaRef, Declarator &D) { switch (D.getDeclSpec().getStorageClassSpec()) { default: llvm_unreachable("Unknown storage class!"); case DeclSpec::SCS_auto: case DeclSpec::SCS_register: case DeclSpec::SCS_mutable: SemaRef.Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::err_typecheck_sclass_func); D.getMutableDeclSpec().ClearStorageClassSpecs(); D.setInvalidType(); break; case DeclSpec::SCS_unspecified: break; case DeclSpec::SCS_extern: if (D.getDeclSpec().isExternInLinkageSpec()) return SC_None; return SC_Extern; case DeclSpec::SCS_static: { if (SemaRef.CurContext->getRedeclContext()->isFunctionOrMethod()) { // C99 6.7.1p5: // The declaration of an identifier for a function that has // block scope shall have no explicit storage-class specifier // other than extern // See also (C++ [dcl.stc]p4). SemaRef.Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::err_static_block_func); break; } else return SC_Static; } case DeclSpec::SCS_private_extern: return SC_PrivateExtern; } // No explicit storage class has already been returned return SC_None; } static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, DeclContext *DC, QualType &R, TypeSourceInfo *TInfo, StorageClass SC, bool &IsVirtualOkay) { DeclarationNameInfo NameInfo = SemaRef.GetNameForDeclarator(D); DeclarationName Name = NameInfo.getName(); FunctionDecl *NewFD = nullptr; bool isInline = D.getDeclSpec().isInlineSpecified(); if (!SemaRef.getLangOpts().CPlusPlus) { // Determine whether the function was written with a // prototype. This true when: // - there is a prototype in the declarator, or // - the type R of the function is some kind of typedef or other non- // attributed reference to a type name (which eventually refers to a // function type). bool HasPrototype = (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || (!R->getAsAdjusted() && R->isFunctionProtoType()); NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getLocStart(), NameInfo, R, TInfo, SC, isInline, HasPrototype, false); if (D.isInvalidType()) NewFD->setInvalidDecl(); return NewFD; } bool isExplicit = D.getDeclSpec().isExplicitSpecified(); bool isConstexpr = D.getDeclSpec().isConstexprSpecified(); // Check that the return type is not an abstract class type. // For record types, this is done by the AbstractClassUsageDiagnoser once // the class has been completely parsed. if (!DC->isRecord() && SemaRef.RequireNonAbstractType( D.getIdentifierLoc(), R->getAs()->getReturnType(), diag::err_abstract_type_in_decl, SemaRef.AbstractReturnType)) D.setInvalidType(); if (Name.getNameKind() == DeclarationName::CXXConstructorName) { // This is a C++ constructor declaration. assert(DC->isRecord() && "Constructors can only be declared in a member context"); R = SemaRef.CheckConstructorDeclarator(D, R, SC); return CXXConstructorDecl::Create(SemaRef.Context, cast(DC), D.getLocStart(), NameInfo, R, TInfo, isExplicit, isInline, /*isImplicitlyDeclared=*/false, isConstexpr); } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { // This is a C++ destructor declaration. if (DC->isRecord()) { R = SemaRef.CheckDestructorDeclarator(D, R, SC); CXXRecordDecl *Record = cast(DC); CXXDestructorDecl *NewDD = CXXDestructorDecl::Create( SemaRef.Context, Record, D.getLocStart(), NameInfo, R, TInfo, isInline, /*isImplicitlyDeclared=*/false); // If the class is complete, then we now create the implicit exception // specification. If the class is incomplete or dependent, we can't do // it yet. if (SemaRef.getLangOpts().CPlusPlus11 && !Record->isDependentType() && Record->getDefinition() && !Record->isBeingDefined() && R->getAs()->getExceptionSpecType() == EST_None) { SemaRef.AdjustDestructorExceptionSpec(Record, NewDD); } IsVirtualOkay = true; return NewDD; } else { SemaRef.Diag(D.getIdentifierLoc(), diag::err_destructor_not_member); D.setInvalidType(); // Create a FunctionDecl to satisfy the function definition parsing // code path. return FunctionDecl::Create(SemaRef.Context, DC, D.getLocStart(), D.getIdentifierLoc(), Name, R, TInfo, SC, isInline, /*hasPrototype=*/true, isConstexpr); } } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { if (!DC->isRecord()) { SemaRef.Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member); return nullptr; } SemaRef.CheckConversionDeclarator(D, R, SC); IsVirtualOkay = true; return CXXConversionDecl::Create(SemaRef.Context, cast(DC), D.getLocStart(), NameInfo, R, TInfo, isInline, isExplicit, isConstexpr, SourceLocation()); } else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) { SemaRef.CheckDeductionGuideDeclarator(D, R, SC); return CXXDeductionGuideDecl::Create(SemaRef.Context, DC, D.getLocStart(), isExplicit, NameInfo, R, TInfo, D.getLocEnd()); } else if (DC->isRecord()) { // If the name of the function is the same as the name of the record, // then this must be an invalid constructor that has a return type. // (The parser checks for a return type and makes the declarator a // constructor if it has no return type). if (Name.getAsIdentifierInfo() && Name.getAsIdentifierInfo() == cast(DC)->getIdentifier()){ SemaRef.Diag(D.getIdentifierLoc(), diag::err_constructor_return_type) << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) << SourceRange(D.getIdentifierLoc()); return nullptr; } // This is a C++ method declaration. CXXMethodDecl *Ret = CXXMethodDecl::Create(SemaRef.Context, cast(DC), D.getLocStart(), NameInfo, R, TInfo, SC, isInline, isConstexpr, SourceLocation()); IsVirtualOkay = !Ret->isStatic(); return Ret; } else { bool isFriend = SemaRef.getLangOpts().CPlusPlus && D.getDeclSpec().isFriendSpecified(); if (!isFriend && SemaRef.CurContext->isRecord()) return nullptr; // Determine whether the function was written with a // prototype. This true when: // - we're in C++ (where every function has a prototype), return FunctionDecl::Create(SemaRef.Context, DC, D.getLocStart(), NameInfo, R, TInfo, SC, isInline, true/*HasPrototype*/, isConstexpr); } } enum OpenCLParamType { ValidKernelParam, PtrPtrKernelParam, PtrKernelParam, InvalidAddrSpacePtrKernelParam, InvalidKernelParam, RecordKernelParam }; static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) { if (PT->isPointerType()) { QualType PointeeType = PT->getPointeeType(); if (PointeeType->isPointerType()) return PtrPtrKernelParam; if (PointeeType.getAddressSpace() == LangAS::opencl_generic || PointeeType.getAddressSpace() == 0) return InvalidAddrSpacePtrKernelParam; return PtrKernelParam; } // TODO: Forbid the other integer types (size_t, ptrdiff_t...) when they can // be used as builtin types. if (PT->isImageType()) return PtrKernelParam; if (PT->isBooleanType() || PT->isEventT() || PT->isReserveIDT()) return InvalidKernelParam; // OpenCL extension spec v1.2 s9.5: // This extension adds support for half scalar and vector types as built-in // types that can be used for arithmetic operations, conversions etc. if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16") && PT->isHalfType()) return InvalidKernelParam; if (PT->isRecordType()) return RecordKernelParam; return ValidKernelParam; } static void checkIsValidOpenCLKernelParameter( Sema &S, Declarator &D, ParmVarDecl *Param, llvm::SmallPtrSetImpl &ValidTypes) { QualType PT = Param->getType(); // Cache the valid types we encounter to avoid rechecking structs that are // used again if (ValidTypes.count(PT.getTypePtr())) return; switch (getOpenCLKernelParameterType(S, PT)) { case PtrPtrKernelParam: // OpenCL v1.2 s6.9.a: // A kernel function argument cannot be declared as a // pointer to a pointer type. S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param); D.setInvalidType(); return; case InvalidAddrSpacePtrKernelParam: // OpenCL v1.0 s6.5: // __kernel function arguments declared to be a pointer of a type can point // to one of the following address spaces only : __global, __local or // __constant. S.Diag(Param->getLocation(), diag::err_kernel_arg_address_space); D.setInvalidType(); return; // OpenCL v1.2 s6.9.k: // Arguments to kernel functions in a program cannot be declared with the // built-in scalar types bool, half, size_t, ptrdiff_t, intptr_t, and // uintptr_t or a struct and/or union that contain fields declared to be // one of these built-in scalar types. case InvalidKernelParam: // OpenCL v1.2 s6.8 n: // A kernel function argument cannot be declared // of event_t type. // Do not diagnose half type since it is diagnosed as invalid argument // type for any function elsewhere. if (!PT->isHalfType()) S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT; D.setInvalidType(); return; case PtrKernelParam: case ValidKernelParam: ValidTypes.insert(PT.getTypePtr()); return; case RecordKernelParam: break; } // Track nested structs we will inspect SmallVector VisitStack; // Track where we are in the nested structs. Items will migrate from // VisitStack to HistoryStack as we do the DFS for bad field. SmallVector HistoryStack; HistoryStack.push_back(nullptr); const RecordDecl *PD = PT->castAs()->getDecl(); VisitStack.push_back(PD); assert(VisitStack.back() && "First decl null?"); do { const Decl *Next = VisitStack.pop_back_val(); if (!Next) { assert(!HistoryStack.empty()); // Found a marker, we have gone up a level if (const FieldDecl *Hist = HistoryStack.pop_back_val()) ValidTypes.insert(Hist->getType().getTypePtr()); continue; } // Adds everything except the original parameter declaration (which is not a // field itself) to the history stack. const RecordDecl *RD; if (const FieldDecl *Field = dyn_cast(Next)) { HistoryStack.push_back(Field); RD = Field->getType()->castAs()->getDecl(); } else { RD = cast(Next); } // Add a null marker so we know when we've gone back up a level VisitStack.push_back(nullptr); for (const auto *FD : RD->fields()) { QualType QT = FD->getType(); if (ValidTypes.count(QT.getTypePtr())) continue; OpenCLParamType ParamType = getOpenCLKernelParameterType(S, QT); if (ParamType == ValidKernelParam) continue; if (ParamType == RecordKernelParam) { VisitStack.push_back(FD); continue; } // OpenCL v1.2 s6.9.p: // Arguments to kernel functions that are declared to be a struct or union // do not allow OpenCL objects to be passed as elements of the struct or // union. if (ParamType == PtrKernelParam || ParamType == PtrPtrKernelParam || ParamType == InvalidAddrSpacePtrKernelParam) { S.Diag(Param->getLocation(), diag::err_record_with_pointers_kernel_param) << PT->isUnionType() << PT; } else { S.Diag(Param->getLocation(), diag::err_bad_kernel_param_type) << PT; } S.Diag(PD->getLocation(), diag::note_within_field_of_type) << PD->getDeclName(); // We have an error, now let's go back up through history and show where // the offending field came from for (ArrayRef::const_iterator I = HistoryStack.begin() + 1, E = HistoryStack.end(); I != E; ++I) { const FieldDecl *OuterField = *I; S.Diag(OuterField->getLocation(), diag::note_within_field_of_type) << OuterField->getType(); } S.Diag(FD->getLocation(), diag::note_illegal_field_declared_here) << QT->isPointerType() << QT; D.setInvalidType(); return; } } while (!VisitStack.empty()); } /// Find the DeclContext in which a tag is implicitly declared if we see an /// elaborated type specifier in the specified context, and lookup finds /// nothing. static DeclContext *getTagInjectionContext(DeclContext *DC) { while (!DC->isFileContext() && !DC->isFunctionOrMethod()) DC = DC->getParent(); return DC; } /// Find the Scope in which a tag is implicitly declared if we see an /// elaborated type specifier in the specified context, and lookup finds /// nothing. static Scope *getTagInjectionScope(Scope *S, const LangOptions &LangOpts) { while (S->isClassScope() || (LangOpts.CPlusPlus && S->isFunctionPrototypeScope()) || ((S->getFlags() & Scope::DeclScope) == 0) || (S->getEntity() && S->getEntity()->isTransparentContext())) S = S->getParent(); return S; } NamedDecl* Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, bool &AddToScope) { QualType R = TInfo->getType(); assert(R.getTypePtr()->isFunctionType()); // TODO: consider using NameInfo for diagnostic. DeclarationNameInfo NameInfo = GetNameForDeclarator(D); DeclarationName Name = NameInfo.getName(); StorageClass SC = getFunctionStorageClass(*this, D); if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), diag::err_invalid_thread) << DeclSpec::getSpecifierName(TSCS); if (D.isFirstDeclarationOfMember()) adjustMemberFunctionCC(R, D.isStaticMember(), D.isCtorOrDtor(), D.getIdentifierLoc()); bool isFriend = false; FunctionTemplateDecl *FunctionTemplate = nullptr; bool isMemberSpecialization = false; bool isFunctionTemplateSpecialization = false; bool isDependentClassScopeExplicitSpecialization = false; bool HasExplicitTemplateArgs = false; TemplateArgumentListInfo TemplateArgs; bool isVirtualOkay = false; DeclContext *OriginalDC = DC; bool IsLocalExternDecl = adjustContextForLocalExternDecl(DC); FunctionDecl *NewFD = CreateNewFunctionDecl(*this, D, DC, R, TInfo, SC, isVirtualOkay); if (!NewFD) return nullptr; if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer()) NewFD->setTopLevelDeclInObjCContainer(); // Set the lexical context. If this is a function-scope declaration, or has a // C++ scope specifier, or is the object of a friend declaration, the lexical // context will be different from the semantic context. NewFD->setLexicalDeclContext(CurContext); if (IsLocalExternDecl) NewFD->setLocalExternDecl(); if (getLangOpts().CPlusPlus) { bool isInline = D.getDeclSpec().isInlineSpecified(); bool isVirtual = D.getDeclSpec().isVirtualSpecified(); bool isExplicit = D.getDeclSpec().isExplicitSpecified(); bool isConstexpr = D.getDeclSpec().isConstexprSpecified(); bool isConcept = D.getDeclSpec().isConceptSpecified(); isFriend = D.getDeclSpec().isFriendSpecified(); if (isFriend && !isInline && D.isFunctionDefinition()) { // C++ [class.friend]p5 // A function can be defined in a friend declaration of a // class . . . . Such a function is implicitly inline. NewFD->setImplicitlyInline(); } // If this is a method defined in an __interface, and is not a constructor // or an overloaded operator, then set the pure flag (isVirtual will already // return true). if (const CXXRecordDecl *Parent = dyn_cast(NewFD->getDeclContext())) { if (Parent->isInterface() && cast(NewFD)->isUserProvided()) NewFD->setPure(true); // C++ [class.union]p2 // A union can have member functions, but not virtual functions. if (isVirtual && Parent->isUnion()) Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_in_union); } SetNestedNameSpecifier(NewFD, D); isMemberSpecialization = false; isFunctionTemplateSpecialization = false; if (D.isInvalidType()) NewFD->setInvalidDecl(); // Match up the template parameter lists with the scope specifier, then // determine whether we have a template or a template specialization. bool Invalid = false; if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( D.getDeclSpec().getLocStart(), D.getIdentifierLoc(), D.getCXXScopeSpec(), D.getName().getKind() == UnqualifiedId::IK_TemplateId ? D.getName().TemplateId : nullptr, TemplateParamLists, isFriend, isMemberSpecialization, Invalid)) { if (TemplateParams->size() > 0) { // This is a function template // Check that we can declare a template here. if (CheckTemplateDeclScope(S, TemplateParams)) NewFD->setInvalidDecl(); // A destructor cannot be a template. if (Name.getNameKind() == DeclarationName::CXXDestructorName) { Diag(NewFD->getLocation(), diag::err_destructor_template); NewFD->setInvalidDecl(); } // If we're adding a template to a dependent context, we may need to // rebuilding some of the types used within the template parameter list, // now that we know what the current instantiation is. if (DC->isDependentContext()) { ContextRAII SavedContext(*this, DC); if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams)) Invalid = true; } FunctionTemplate = FunctionTemplateDecl::Create(Context, DC, NewFD->getLocation(), Name, TemplateParams, NewFD); FunctionTemplate->setLexicalDeclContext(CurContext); NewFD->setDescribedFunctionTemplate(FunctionTemplate); // For source fidelity, store the other template param lists. if (TemplateParamLists.size() > 1) { NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists.drop_back(1)); } } else { // This is a function template specialization. isFunctionTemplateSpecialization = true; // For source fidelity, store all the template param lists. if (TemplateParamLists.size() > 0) NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists); // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);". if (isFriend) { // We want to remove the "template<>", found here. SourceRange RemoveRange = TemplateParams->getSourceRange(); // If we remove the template<> and the name is not a // template-id, we're actually silently creating a problem: // the friend declaration will refer to an untemplated decl, // and clearly the user wants a template specialization. So // we need to insert '<>' after the name. SourceLocation InsertLoc; if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) { InsertLoc = D.getName().getSourceRange().getEnd(); InsertLoc = getLocForEndOfToken(InsertLoc); } Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend) << Name << RemoveRange << FixItHint::CreateRemoval(RemoveRange) << FixItHint::CreateInsertion(InsertLoc, "<>"); } } } else { // All template param lists were matched against the scope specifier: // this is NOT (an explicit specialization of) a template. if (TemplateParamLists.size() > 0) // For source fidelity, store all the template param lists. NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists); } if (Invalid) { NewFD->setInvalidDecl(); if (FunctionTemplate) FunctionTemplate->setInvalidDecl(); } // C++ [dcl.fct.spec]p5: // The virtual specifier shall only be used in declarations of // nonstatic class member functions that appear within a // member-specification of a class declaration; see 10.3. // if (isVirtual && !NewFD->isInvalidDecl()) { if (!isVirtualOkay) { Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_non_function); } else if (!CurContext->isRecord()) { // 'virtual' was specified outside of the class. Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_out_of_class) << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc()); } else if (NewFD->getDescribedFunctionTemplate()) { // C++ [temp.mem]p3: // A member function template shall not be virtual. Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_virtual_member_function_template) << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc()); } else { // Okay: Add virtual to the method. NewFD->setVirtualAsWritten(true); } if (getLangOpts().CPlusPlus14 && NewFD->getReturnType()->isUndeducedType()) Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual); } if (getLangOpts().CPlusPlus14 && (NewFD->isDependentContext() || (isFriend && CurContext->isDependentContext())) && NewFD->getReturnType()->isUndeducedType()) { // If the function template is referenced directly (for instance, as a // member of the current instantiation), pretend it has a dependent type. // This is not really justified by the standard, but is the only sane // thing to do. // FIXME: For a friend function, we have not marked the function as being // a friend yet, so 'isDependentContext' on the FD doesn't work. const FunctionProtoType *FPT = NewFD->getType()->castAs(); QualType Result = SubstAutoType(FPT->getReturnType(), Context.DependentTy); NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(), FPT->getExtProtoInfo())); } // C++ [dcl.fct.spec]p3: // The inline specifier shall not appear on a block scope function // declaration. if (isInline && !NewFD->isInvalidDecl()) { if (CurContext->isFunctionOrMethod()) { // 'inline' is not allowed on block scope function declaration. Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_declaration_block_scope) << Name << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc()); } } // C++ [dcl.fct.spec]p6: // The explicit specifier shall be used only in the declaration of a // constructor or conversion function within its class definition; // see 12.3.1 and 12.3.2. if (isExplicit && !NewFD->isInvalidDecl() && !isa(NewFD)) { if (!CurContext->isRecord()) { // 'explicit' was specified outside of the class. Diag(D.getDeclSpec().getExplicitSpecLoc(), diag::err_explicit_out_of_class) << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc()); } else if (!isa(NewFD) && !isa(NewFD)) { // 'explicit' was specified on a function that wasn't a constructor // or conversion function. Diag(D.getDeclSpec().getExplicitSpecLoc(), diag::err_explicit_non_ctor_or_conv_function) << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc()); } } if (isConstexpr) { // C++11 [dcl.constexpr]p2: constexpr functions and constexpr constructors // are implicitly inline. NewFD->setImplicitlyInline(); // C++11 [dcl.constexpr]p3: functions declared constexpr are required to // be either constructors or to return a literal type. Therefore, // destructors cannot be declared constexpr. if (isa(NewFD)) Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor); } if (isConcept) { // This is a function concept. if (FunctionTemplateDecl *FTD = NewFD->getDescribedFunctionTemplate()) FTD->setConcept(); // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be // applied only to the definition of a function template [...] if (!D.isFunctionDefinition()) { Diag(D.getDeclSpec().getConceptSpecLoc(), diag::err_function_concept_not_defined); NewFD->setInvalidDecl(); } // C++ Concepts TS [dcl.spec.concept]p1: [...] A function concept shall // have no exception-specification and is treated as if it were specified // with noexcept(true) (15.4). [...] if (const FunctionProtoType *FPT = R->getAs()) { if (FPT->hasExceptionSpec()) { SourceRange Range; if (D.isFunctionDeclarator()) Range = D.getFunctionTypeInfo().getExceptionSpecRange(); Diag(NewFD->getLocation(), diag::err_function_concept_exception_spec) << FixItHint::CreateRemoval(Range); NewFD->setInvalidDecl(); } else { Context.adjustExceptionSpec(NewFD, EST_BasicNoexcept); } // C++ Concepts TS [dcl.spec.concept]p5: A function concept has the // following restrictions: // - The declared return type shall have the type bool. if (!Context.hasSameType(FPT->getReturnType(), Context.BoolTy)) { Diag(D.getIdentifierLoc(), diag::err_function_concept_bool_ret); NewFD->setInvalidDecl(); } // C++ Concepts TS [dcl.spec.concept]p5: A function concept has the // following restrictions: // - The declaration's parameter list shall be equivalent to an empty // parameter list. if (FPT->getNumParams() > 0 || FPT->isVariadic()) Diag(NewFD->getLocation(), diag::err_function_concept_with_params); } // C++ Concepts TS [dcl.spec.concept]p2: Every concept definition is // implicity defined to be a constexpr declaration (implicitly inline) NewFD->setImplicitlyInline(); // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not // be declared with the thread_local, inline, friend, or constexpr // specifiers, [...] if (isInline) { Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_concept_decl_invalid_specifiers) << 1 << 1; NewFD->setInvalidDecl(true); } if (isFriend) { Diag(D.getDeclSpec().getFriendSpecLoc(), diag::err_concept_decl_invalid_specifiers) << 1 << 2; NewFD->setInvalidDecl(true); } if (isConstexpr) { Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_concept_decl_invalid_specifiers) << 1 << 3; NewFD->setInvalidDecl(true); } // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be // applied only to the definition of a function template or variable // template, declared in namespace scope. if (isFunctionTemplateSpecialization) { Diag(D.getDeclSpec().getConceptSpecLoc(), diag::err_concept_specified_specialization) << 1; NewFD->setInvalidDecl(true); return NewFD; } } // If __module_private__ was specified, mark the function accordingly. if (D.getDeclSpec().isModulePrivateSpecified()) { if (isFunctionTemplateSpecialization) { SourceLocation ModulePrivateLoc = D.getDeclSpec().getModulePrivateSpecLoc(); Diag(ModulePrivateLoc, diag::err_module_private_specialization) << 0 << FixItHint::CreateRemoval(ModulePrivateLoc); } else { NewFD->setModulePrivate(); if (FunctionTemplate) FunctionTemplate->setModulePrivate(); } } if (isFriend) { if (FunctionTemplate) { FunctionTemplate->setObjectOfFriendDecl(); FunctionTemplate->setAccess(AS_public); } NewFD->setObjectOfFriendDecl(); NewFD->setAccess(AS_public); } // If a function is defined as defaulted or deleted, mark it as such now. // FIXME: Does this ever happen? ActOnStartOfFunctionDef forces the function // definition kind to FDK_Definition. switch (D.getFunctionDefinitionKind()) { case FDK_Declaration: case FDK_Definition: break; case FDK_Defaulted: NewFD->setDefaulted(); break; case FDK_Deleted: NewFD->setDeletedAsWritten(); break; } if (isa(NewFD) && DC == CurContext && D.isFunctionDefinition()) { // C++ [class.mfct]p2: // A member function may be defined (8.4) in its class definition, in // which case it is an inline member function (7.1.2) NewFD->setImplicitlyInline(); } if (SC == SC_Static && isa(NewFD) && !CurContext->isRecord()) { // C++ [class.static]p1: // A data or function member of a class may be declared static // in a class definition, in which case it is a static member of // the class. // Complain about the 'static' specifier if it's on an out-of-line // member function definition. Diag(D.getDeclSpec().getStorageClassSpecLoc(), diag::err_static_out_of_line) << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); } // C++11 [except.spec]p15: // A deallocation function with no exception-specification is treated // as if it were specified with noexcept(true). const FunctionProtoType *FPT = R->getAs(); if ((Name.getCXXOverloadedOperator() == OO_Delete || Name.getCXXOverloadedOperator() == OO_Array_Delete) && getLangOpts().CPlusPlus11 && FPT && !FPT->hasExceptionSpec()) NewFD->setType(Context.getFunctionType( FPT->getReturnType(), FPT->getParamTypes(), FPT->getExtProtoInfo().withExceptionSpec(EST_BasicNoexcept))); } // Filter out previous declarations that don't match the scope. FilterLookupForScope(Previous, OriginalDC, S, shouldConsiderLinkage(NewFD), D.getCXXScopeSpec().isNotEmpty() || isMemberSpecialization || isFunctionTemplateSpecialization); // Handle GNU asm-label extension (encoded as an attribute). if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast(E); NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context, SE->getString(), 0)); } else if (!ExtnameUndeclaredIdentifiers.empty()) { llvm::DenseMap::iterator I = ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier()); if (I != ExtnameUndeclaredIdentifiers.end()) { if (isDeclExternC(NewFD)) { NewFD->addAttr(I->second); ExtnameUndeclaredIdentifiers.erase(I); } else Diag(NewFD->getLocation(), diag::warn_redefine_extname_not_applied) << /*Variable*/0 << NewFD; } } // Copy the parameter declarations from the declarator D to the function // declaration NewFD, if they are available. First scavenge them into Params. SmallVector Params; unsigned FTIIdx; if (D.isFunctionDeclarator(FTIIdx)) { DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(FTIIdx).Fun; // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs // function that takes no arguments, not a function that takes a // single void argument. // We let through "const void" here because Sema::GetTypeForDeclarator // already checks for that case. if (FTIHasNonVoidParameters(FTI) && FTI.Params[0].Param) { for (unsigned i = 0, e = FTI.NumParams; i != e; ++i) { ParmVarDecl *Param = cast(FTI.Params[i].Param); assert(Param->getDeclContext() != NewFD && "Was set before ?"); Param->setDeclContext(NewFD); Params.push_back(Param); if (Param->isInvalidDecl()) NewFD->setInvalidDecl(); } } if (!getLangOpts().CPlusPlus) { // In C, find all the tag declarations from the prototype and move them // into the function DeclContext. Remove them from the surrounding tag // injection context of the function, which is typically but not always // the TU. DeclContext *PrototypeTagContext = getTagInjectionContext(NewFD->getLexicalDeclContext()); for (NamedDecl *NonParmDecl : FTI.getDeclsInPrototype()) { auto *TD = dyn_cast(NonParmDecl); // We don't want to reparent enumerators. Look at their parent enum // instead. if (!TD) { if (auto *ECD = dyn_cast(NonParmDecl)) TD = cast(ECD->getDeclContext()); } if (!TD) continue; DeclContext *TagDC = TD->getLexicalDeclContext(); if (!TagDC->containsDecl(TD)) continue; TagDC->removeDecl(TD); TD->setDeclContext(NewFD); NewFD->addDecl(TD); // Preserve the lexical DeclContext if it is not the surrounding tag // injection context of the FD. In this example, the semantic context of // E will be f and the lexical context will be S, while both the // semantic and lexical contexts of S will be f: // void f(struct S { enum E { a } f; } s); if (TagDC != PrototypeTagContext) TD->setLexicalDeclContext(TagDC); } } } else if (const FunctionProtoType *FT = R->getAs()) { // When we're declaring a function with a typedef, typeof, etc as in the // following example, we'll need to synthesize (unnamed) // parameters for use in the declaration. // // @code // typedef void fn(int); // fn f; // @endcode // Synthesize a parameter for each argument type. for (const auto &AI : FT->param_types()) { ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), AI); Param->setScopeInfo(0, Params.size()); Params.push_back(Param); } } else { assert(R->isFunctionNoProtoType() && NewFD->getNumParams() == 0 && "Should not need args for typedef of non-prototype fn"); } // Finally, we know we have the right number of parameters, install them. NewFD->setParams(Params); if (D.getDeclSpec().isNoreturnSpecified()) NewFD->addAttr( ::new(Context) C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(), Context, 0)); // Functions returning a variably modified type violate C99 6.7.5.2p2 // because all functions have linkage. if (!NewFD->isInvalidDecl() && NewFD->getReturnType()->isVariablyModifiedType()) { Diag(NewFD->getLocation(), diag::err_vm_func_decl); NewFD->setInvalidDecl(); } // Apply an implicit SectionAttr if '#pragma clang section text' is active if (PragmaClangTextSection.Valid && D.isFunctionDefinition() && !NewFD->hasAttr()) { NewFD->addAttr(PragmaClangTextSectionAttr::CreateImplicit(Context, PragmaClangTextSection.SectionName, PragmaClangTextSection.PragmaLocation)); } // Apply an implicit SectionAttr if #pragma code_seg is active. if (CodeSegStack.CurrentValue && D.isFunctionDefinition() && !NewFD->hasAttr()) { NewFD->addAttr( SectionAttr::CreateImplicit(Context, SectionAttr::Declspec_allocate, CodeSegStack.CurrentValue->getString(), CodeSegStack.CurrentPragmaLocation)); if (UnifySection(CodeSegStack.CurrentValue->getString(), ASTContext::PSF_Implicit | ASTContext::PSF_Execute | ASTContext::PSF_Read, NewFD)) NewFD->dropAttr(); } // Handle attributes. ProcessDeclAttributes(S, NewFD, D); if (getLangOpts().OpenCL) { // OpenCL v1.1 s6.5: Using an address space qualifier in a function return // type declaration will generate a compilation error. unsigned AddressSpace = NewFD->getReturnType().getAddressSpace(); if (AddressSpace == LangAS::opencl_local || AddressSpace == LangAS::opencl_global || AddressSpace == LangAS::opencl_constant) { Diag(NewFD->getLocation(), diag::err_opencl_return_value_with_address_space); NewFD->setInvalidDecl(); } } if (!getLangOpts().CPlusPlus) { // Perform semantic checking on the function declaration. if (!NewFD->isInvalidDecl() && NewFD->isMain()) CheckMain(NewFD, D.getDeclSpec()); if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint()) CheckMSVCRTEntryPoint(NewFD); if (!NewFD->isInvalidDecl()) D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, isMemberSpecialization)); else if (!Previous.empty()) // Recover gracefully from an invalid redeclaration. D.setRedeclaration(true); assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || Previous.getResultKind() != LookupResult::FoundOverloaded) && "previous declaration set still overloaded"); // Diagnose no-prototype function declarations with calling conventions that // don't support variadic calls. Only do this in C and do it after merging // possibly prototyped redeclarations. const FunctionType *FT = NewFD->getType()->castAs(); if (isa(FT) && !D.isFunctionDefinition()) { CallingConv CC = FT->getExtInfo().getCC(); if (!supportsVariadicCall(CC)) { // Windows system headers sometimes accidentally use stdcall without // (void) parameters, so we relax this to a warning. int DiagID = CC == CC_X86StdCall ? diag::warn_cconv_knr : diag::err_cconv_knr; Diag(NewFD->getLocation(), DiagID) << FunctionType::getNameForCallConv(CC); } } } else { // C++11 [replacement.functions]p3: // The program's definitions shall not be specified as inline. // // N.B. We diagnose declarations instead of definitions per LWG issue 2340. // // Suppress the diagnostic if the function is __attribute__((used)), since // that forces an external definition to be emitted. if (D.getDeclSpec().isInlineSpecified() && NewFD->isReplaceableGlobalAllocationFunction() && !NewFD->hasAttr()) Diag(D.getDeclSpec().getInlineSpecLoc(), diag::ext_operator_new_delete_declared_inline) << NewFD->getDeclName(); // If the declarator is a template-id, translate the parser's template // argument list into our AST format. if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { TemplateIdAnnotation *TemplateId = D.getName().TemplateId; TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc); TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc); ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); translateTemplateArguments(TemplateArgsPtr, TemplateArgs); HasExplicitTemplateArgs = true; if (NewFD->isInvalidDecl()) { HasExplicitTemplateArgs = false; } else if (FunctionTemplate) { // Function template with explicit template arguments. Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec) << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc); HasExplicitTemplateArgs = false; } else { assert((isFunctionTemplateSpecialization || D.getDeclSpec().isFriendSpecified()) && "should have a 'template<>' for this decl"); // "friend void foo<>(int);" is an implicit specialization decl. isFunctionTemplateSpecialization = true; } } else if (isFriend && isFunctionTemplateSpecialization) { // This combination is only possible in a recovery case; the user // wrote something like: // template <> friend void foo(int); // which we're recovering from as if the user had written: // friend void foo<>(int); // Go ahead and fake up a template id. HasExplicitTemplateArgs = true; TemplateArgs.setLAngleLoc(D.getIdentifierLoc()); TemplateArgs.setRAngleLoc(D.getIdentifierLoc()); } // We do not add HD attributes to specializations here because // they may have different constexpr-ness compared to their // templates and, after maybeAddCUDAHostDeviceAttrs() is applied, // may end up with different effective targets. Instead, a // specialization inherits its target attributes from its template // in the CheckFunctionTemplateSpecialization() call below. if (getLangOpts().CUDA & !isFunctionTemplateSpecialization) maybeAddCUDAHostDeviceAttrs(NewFD, Previous); // If it's a friend (and only if it's a friend), it's possible // that either the specialized function type or the specialized // template is dependent, and therefore matching will fail. In // this case, don't check the specialization yet. bool InstantiationDependent = false; if (isFunctionTemplateSpecialization && isFriend && (NewFD->getType()->isDependentType() || DC->isDependentContext() || TemplateSpecializationType::anyDependentTemplateArguments( TemplateArgs, InstantiationDependent))) { assert(HasExplicitTemplateArgs && "friend function specialization without template args"); if (CheckDependentFunctionTemplateSpecialization(NewFD, TemplateArgs, Previous)) NewFD->setInvalidDecl(); } else if (isFunctionTemplateSpecialization) { if (CurContext->isDependentContext() && CurContext->isRecord() && !isFriend) { isDependentClassScopeExplicitSpecialization = true; Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ? diag::ext_function_specialization_in_class : diag::err_function_specialization_in_class) << NewFD->getDeclName(); } else if (CheckFunctionTemplateSpecialization(NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr), Previous)) NewFD->setInvalidDecl(); // C++ [dcl.stc]p1: // A storage-class-specifier shall not be specified in an explicit // specialization (14.7.3) FunctionTemplateSpecializationInfo *Info = NewFD->getTemplateSpecializationInfo(); if (Info && SC != SC_None) { if (SC != Info->getTemplate()->getTemplatedDecl()->getStorageClass()) Diag(NewFD->getLocation(), diag::err_explicit_specialization_inconsistent_storage_class) << SC << FixItHint::CreateRemoval( D.getDeclSpec().getStorageClassSpecLoc()); else Diag(NewFD->getLocation(), diag::ext_explicit_specialization_storage_class) << FixItHint::CreateRemoval( D.getDeclSpec().getStorageClassSpecLoc()); } } else if (isMemberSpecialization && isa(NewFD)) { if (CheckMemberSpecialization(NewFD, Previous)) NewFD->setInvalidDecl(); } // Perform semantic checking on the function declaration. if (!isDependentClassScopeExplicitSpecialization) { if (!NewFD->isInvalidDecl() && NewFD->isMain()) CheckMain(NewFD, D.getDeclSpec()); if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint()) CheckMSVCRTEntryPoint(NewFD); if (!NewFD->isInvalidDecl()) D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, isMemberSpecialization)); else if (!Previous.empty()) // Recover gracefully from an invalid redeclaration. D.setRedeclaration(true); } assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || Previous.getResultKind() != LookupResult::FoundOverloaded) && "previous declaration set still overloaded"); NamedDecl *PrincipalDecl = (FunctionTemplate ? cast(FunctionTemplate) : NewFD); if (isFriend && NewFD->getPreviousDecl()) { AccessSpecifier Access = AS_public; if (!NewFD->isInvalidDecl()) Access = NewFD->getPreviousDecl()->getAccess(); NewFD->setAccess(Access); if (FunctionTemplate) FunctionTemplate->setAccess(Access); } if (NewFD->isOverloadedOperator() && !DC->isRecord() && PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) PrincipalDecl->setNonMemberOperator(); // If we have a function template, check the template parameter // list. This will check and merge default template arguments. if (FunctionTemplate) { FunctionTemplateDecl *PrevTemplate = FunctionTemplate->getPreviousDecl(); CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(), PrevTemplate ? PrevTemplate->getTemplateParameters() : nullptr, D.getDeclSpec().isFriendSpecified() ? (D.isFunctionDefinition() ? TPC_FriendFunctionTemplateDefinition : TPC_FriendFunctionTemplate) : (D.getCXXScopeSpec().isSet() && DC && DC->isRecord() && DC->isDependentContext()) ? TPC_ClassTemplateMember : TPC_FunctionTemplate); } if (NewFD->isInvalidDecl()) { // Ignore all the rest of this. } else if (!D.isRedeclaration()) { struct ActOnFDArgs ExtraArgs = { S, D, TemplateParamLists, AddToScope }; // Fake up an access specifier if it's supposed to be a class member. if (isa(NewFD->getDeclContext())) NewFD->setAccess(AS_public); // Qualified decls generally require a previous declaration. if (D.getCXXScopeSpec().isSet()) { // ...with the major exception of templated-scope or // dependent-scope friend declarations. // TODO: we currently also suppress this check in dependent // contexts because (1) the parameter depth will be off when // matching friend templates and (2) we might actually be // selecting a friend based on a dependent factor. But there // are situations where these conditions don't apply and we // can actually do this check immediately. if (isFriend && (TemplateParamLists.size() || D.getCXXScopeSpec().getScopeRep()->isDependent() || CurContext->isDependentContext())) { // ignore these } else { // The user tried to provide an out-of-line definition for a // function that is a member of a class or namespace, but there // was no such member function declared (C++ [class.mfct]p2, // C++ [namespace.memdef]p2). For example: // // class X { // void f() const; // }; // // void X::f() { } // ill-formed // // Complain about this problem, and attempt to suggest close // matches (e.g., those that differ only in cv-qualifiers and // whether the parameter types are references). if (NamedDecl *Result = DiagnoseInvalidRedeclaration( *this, Previous, NewFD, ExtraArgs, false, nullptr)) { AddToScope = ExtraArgs.AddToScope; return Result; } } // Unqualified local friend declarations are required to resolve // to something. } else if (isFriend && cast(CurContext)->isLocalClass()) { if (NamedDecl *Result = DiagnoseInvalidRedeclaration( *this, Previous, NewFD, ExtraArgs, true, S)) { AddToScope = ExtraArgs.AddToScope; return Result; } } } else if (!D.isFunctionDefinition() && isa(NewFD) && NewFD->isOutOfLine() && !isFriend && !isFunctionTemplateSpecialization && !isMemberSpecialization) { // An out-of-line member function declaration must also be a // definition (C++ [class.mfct]p2). // Note that this is not the case for explicit specializations of // function templates or member functions of class templates, per // C++ [temp.expl.spec]p2. We also allow these declarations as an // extension for compatibility with old SWIG code which likes to // generate them. Diag(NewFD->getLocation(), diag::ext_out_of_line_declaration) << D.getCXXScopeSpec().getRange(); } } ProcessPragmaWeak(S, NewFD); checkAttributesAfterMerging(*this, *NewFD); AddKnownFunctionAttributes(NewFD); if (NewFD->hasAttr() && !NewFD->getType()->getAs()) { Diag(NewFD->getLocation(), diag::err_attribute_overloadable_no_prototype) << NewFD; // Turn this into a variadic function with no parameters. const FunctionType *FT = NewFD->getType()->getAs(); FunctionProtoType::ExtProtoInfo EPI( Context.getDefaultCallingConvention(true, false)); EPI.Variadic = true; EPI.ExtInfo = FT->getExtInfo(); QualType R = Context.getFunctionType(FT->getReturnType(), None, EPI); NewFD->setType(R); } // If there's a #pragma GCC visibility in scope, and this isn't a class // member, set the visibility of this function. if (!DC->isRecord() && NewFD->isExternallyVisible()) AddPushedVisibilityAttribute(NewFD); // If there's a #pragma clang arc_cf_code_audited in scope, consider // marking the function. AddCFAuditedAttribute(NewFD); // If this is a function definition, check if we have to apply optnone due to // a pragma. if(D.isFunctionDefinition()) AddRangeBasedOptnone(NewFD); // If this is the first declaration of an extern C variable, update // the map of such variables. if (NewFD->isFirstDecl() && !NewFD->isInvalidDecl() && isIncompleteDeclExternC(*this, NewFD)) RegisterLocallyScopedExternCDecl(NewFD, S); // Set this FunctionDecl's range up to the right paren. NewFD->setRangeEnd(D.getSourceRange().getEnd()); if (D.isRedeclaration() && !Previous.empty()) { checkDLLAttributeRedeclaration( *this, dyn_cast(Previous.getRepresentativeDecl()), NewFD, isMemberSpecialization || isFunctionTemplateSpecialization, D.isFunctionDefinition()); } if (getLangOpts().CUDA) { IdentifierInfo *II = NewFD->getIdentifier(); if (II && II->isStr("cudaConfigureCall") && !NewFD->isInvalidDecl() && NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { if (!R->getAs()->getReturnType()->isScalarType()) Diag(NewFD->getLocation(), diag::err_config_scalar_return); Context.setcudaConfigureCallDecl(NewFD); } // Variadic functions, other than a *declaration* of printf, are not allowed // in device-side CUDA code, unless someone passed // -fcuda-allow-variadic-functions. if (!getLangOpts().CUDAAllowVariadicFunctions && NewFD->isVariadic() && (NewFD->hasAttr() || NewFD->hasAttr()) && !(II && II->isStr("printf") && NewFD->isExternC() && !D.isFunctionDefinition())) { Diag(NewFD->getLocation(), diag::err_variadic_device_fn); } } MarkUnusedFileScopedDecl(NewFD); if (getLangOpts().CPlusPlus) { if (FunctionTemplate) { if (NewFD->isInvalidDecl()) FunctionTemplate->setInvalidDecl(); return FunctionTemplate; } if (isMemberSpecialization && !NewFD->isInvalidDecl()) CompleteMemberSpecialization(NewFD, Previous); } if (NewFD->hasAttr()) { // OpenCL v1.2 s6.8 static is invalid for kernel functions. if ((getLangOpts().OpenCLVersion >= 120) && (SC == SC_Static)) { Diag(D.getIdentifierLoc(), diag::err_static_kernel); D.setInvalidType(); } // OpenCL v1.2, s6.9 -- Kernels can only have return type void. if (!NewFD->getReturnType()->isVoidType()) { SourceRange RTRange = NewFD->getReturnTypeSourceRange(); Diag(D.getIdentifierLoc(), diag::err_expected_kernel_void_return_type) << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "void") : FixItHint()); D.setInvalidType(); } llvm::SmallPtrSet ValidTypes; for (auto Param : NewFD->parameters()) checkIsValidOpenCLKernelParameter(*this, D, Param, ValidTypes); } for (const ParmVarDecl *Param : NewFD->parameters()) { QualType PT = Param->getType(); // OpenCL 2.0 pipe restrictions forbids pipe packet types to be non-value // types. if (getLangOpts().OpenCLVersion >= 200) { if(const PipeType *PipeTy = PT->getAs()) { QualType ElemTy = PipeTy->getElementType(); if (ElemTy->isReferenceType() || ElemTy->isPointerType()) { Diag(Param->getTypeSpecStartLoc(), diag::err_reference_pipe_type ); D.setInvalidType(); } } } } // Here we have an function template explicit specialization at class scope. // The actually specialization will be postponed to template instatiation // time via the ClassScopeFunctionSpecializationDecl node. if (isDependentClassScopeExplicitSpecialization) { ClassScopeFunctionSpecializationDecl *NewSpec = ClassScopeFunctionSpecializationDecl::Create( Context, CurContext, SourceLocation(), cast(NewFD), HasExplicitTemplateArgs, TemplateArgs); CurContext->addDecl(NewSpec); AddToScope = false; } return NewFD; } /// \brief Checks if the new declaration declared in dependent context must be /// put in the same redeclaration chain as the specified declaration. /// /// \param D Declaration that is checked. /// \param PrevDecl Previous declaration found with proper lookup method for the /// same declaration name. /// \returns True if D must be added to the redeclaration chain which PrevDecl /// belongs to. /// bool Sema::shouldLinkDependentDeclWithPrevious(Decl *D, Decl *PrevDecl) { // Any declarations should be put into redeclaration chains except for // friend declaration in a dependent context that names a function in // namespace scope. // // This allows to compile code like: // // void func(); // template class C1 { friend void func() { } }; // template class C2 { friend void func() { } }; // // This code snippet is a valid code unless both templates are instantiated. return !(D->getLexicalDeclContext()->isDependentContext() && D->getDeclContext()->isFileContext() && D->getFriendObjectKind() != Decl::FOK_None); } /// \brief Perform semantic checking of a new function declaration. /// /// Performs semantic analysis of the new function declaration /// NewFD. This routine performs all semantic checking that does not /// require the actual declarator involved in the declaration, and is /// used both for the declaration of functions as they are parsed /// (called via ActOnDeclarator) and for the declaration of functions /// that have been instantiated via C++ template instantiation (called /// via InstantiateDecl). /// /// \param IsMemberSpecialization whether this new function declaration is /// a member specialization (that replaces any definition provided by the /// previous declaration). /// /// This sets NewFD->isInvalidDecl() to true if there was an error. /// /// \returns true if the function declaration is a redeclaration. bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, LookupResult &Previous, bool IsMemberSpecialization) { assert(!NewFD->getReturnType()->isVariablyModifiedType() && "Variably modified return types are not handled here"); // Determine whether the type of this function should be merged with // a previous visible declaration. This never happens for functions in C++, // and always happens in C if the previous declaration was visible. bool MergeTypeWithPrevious = !getLangOpts().CPlusPlus && !Previous.isShadowed(); bool Redeclaration = false; NamedDecl *OldDecl = nullptr; bool MayNeedOverloadableChecks = false; // Merge or overload the declaration with an existing declaration of // the same name, if appropriate. if (!Previous.empty()) { // Determine whether NewFD is an overload of PrevDecl or // a declaration that requires merging. If it's an overload, // there's no more work to do here; we'll just add the new // function to the scope. if (!AllowOverloadingOfFunction(Previous, Context, NewFD)) { NamedDecl *Candidate = Previous.getRepresentativeDecl(); if (shouldLinkPossiblyHiddenDecl(Candidate, NewFD)) { Redeclaration = true; OldDecl = Candidate; } } else { MayNeedOverloadableChecks = true; switch (CheckOverload(S, NewFD, Previous, OldDecl, /*NewIsUsingDecl*/ false)) { case Ovl_Match: Redeclaration = true; break; case Ovl_NonFunction: Redeclaration = true; break; case Ovl_Overload: Redeclaration = false; break; } } } // Check for a previous extern "C" declaration with this name. if (!Redeclaration && checkForConflictWithNonVisibleExternC(*this, NewFD, Previous)) { if (!Previous.empty()) { // This is an extern "C" declaration with the same name as a previous // declaration, and thus redeclares that entity... Redeclaration = true; OldDecl = Previous.getFoundDecl(); MergeTypeWithPrevious = false; // ... except in the presence of __attribute__((overloadable)). if (OldDecl->hasAttr() || NewFD->hasAttr()) { if (IsOverload(NewFD, cast(OldDecl), false)) { MayNeedOverloadableChecks = true; Redeclaration = false; OldDecl = nullptr; } } } } // C++11 [dcl.constexpr]p8: // A constexpr specifier for a non-static member function that is not // a constructor declares that member function to be const. // // This needs to be delayed until we know whether this is an out-of-line // definition of a static member function. // // This rule is not present in C++1y, so we produce a backwards // compatibility warning whenever it happens in C++11. CXXMethodDecl *MD = dyn_cast(NewFD); if (!getLangOpts().CPlusPlus14 && MD && MD->isConstexpr() && !MD->isStatic() && !isa(MD) && (MD->getTypeQualifiers() & Qualifiers::Const) == 0) { CXXMethodDecl *OldMD = nullptr; if (OldDecl) OldMD = dyn_cast_or_null(OldDecl->getAsFunction()); if (!OldMD || !OldMD->isStatic()) { const FunctionProtoType *FPT = MD->getType()->castAs(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.TypeQuals |= Qualifiers::Const; MD->setType(Context.getFunctionType(FPT->getReturnType(), FPT->getParamTypes(), EPI)); // Warn that we did this, if we're not performing template instantiation. // In that case, we'll have warned already when the template was defined. if (!inTemplateInstantiation()) { SourceLocation AddConstLoc; if (FunctionTypeLoc FTL = MD->getTypeSourceInfo()->getTypeLoc() .IgnoreParens().getAs()) AddConstLoc = getLocForEndOfToken(FTL.getRParenLoc()); Diag(MD->getLocation(), diag::warn_cxx14_compat_constexpr_not_const) << FixItHint::CreateInsertion(AddConstLoc, " const"); } } } if (Redeclaration) { // NewFD and OldDecl represent declarations that need to be // merged. if (MergeFunctionDecl(NewFD, OldDecl, S, MergeTypeWithPrevious)) { NewFD->setInvalidDecl(); return Redeclaration; } Previous.clear(); Previous.addDecl(OldDecl); if (FunctionTemplateDecl *OldTemplateDecl = dyn_cast(OldDecl)) { NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl()); FunctionTemplateDecl *NewTemplateDecl = NewFD->getDescribedFunctionTemplate(); assert(NewTemplateDecl && "Template/non-template mismatch"); if (CXXMethodDecl *Method = dyn_cast(NewTemplateDecl->getTemplatedDecl())) { Method->setAccess(OldTemplateDecl->getAccess()); NewTemplateDecl->setAccess(OldTemplateDecl->getAccess()); } // If this is an explicit specialization of a member that is a function // template, mark it as a member specialization. if (IsMemberSpecialization && NewTemplateDecl->getInstantiatedFromMemberTemplate()) { NewTemplateDecl->setMemberSpecialization(); assert(OldTemplateDecl->isMemberSpecialization()); // Explicit specializations of a member template do not inherit deleted // status from the parent member template that they are specializing. if (OldTemplateDecl->getTemplatedDecl()->isDeleted()) { FunctionDecl *const OldTemplatedDecl = OldTemplateDecl->getTemplatedDecl(); // FIXME: This assert will not hold in the presence of modules. assert(OldTemplatedDecl->getCanonicalDecl() == OldTemplatedDecl); // FIXME: We need an update record for this AST mutation. OldTemplatedDecl->setDeletedAsWritten(false); } } } else { if (shouldLinkDependentDeclWithPrevious(NewFD, OldDecl)) { // This needs to happen first so that 'inline' propagates. NewFD->setPreviousDeclaration(cast(OldDecl)); if (isa(NewFD)) NewFD->setAccess(OldDecl->getAccess()); } } } else if (!getLangOpts().CPlusPlus && MayNeedOverloadableChecks && !NewFD->getAttr()) { assert((Previous.empty() || llvm::any_of(Previous, [](const NamedDecl *ND) { return ND->hasAttr(); })) && "Non-redecls shouldn't happen without overloadable present"); auto OtherUnmarkedIter = llvm::find_if(Previous, [](const NamedDecl *ND) { const auto *FD = dyn_cast(ND); return FD && !FD->hasAttr(); }); if (OtherUnmarkedIter != Previous.end()) { Diag(NewFD->getLocation(), diag::err_attribute_overloadable_multiple_unmarked_overloads); Diag((*OtherUnmarkedIter)->getLocation(), diag::note_attribute_overloadable_prev_overload) << false; NewFD->addAttr(OverloadableAttr::CreateImplicit(Context)); } } // Semantic checking for this function declaration (in isolation). if (getLangOpts().CPlusPlus) { // C++-specific checks. if (CXXConstructorDecl *Constructor = dyn_cast(NewFD)) { CheckConstructor(Constructor); } else if (CXXDestructorDecl *Destructor = dyn_cast(NewFD)) { CXXRecordDecl *Record = Destructor->getParent(); QualType ClassType = Context.getTypeDeclType(Record); // FIXME: Shouldn't we be able to perform this check even when the class // type is dependent? Both gcc and edg can handle that. if (!ClassType->isDependentType()) { DeclarationName Name = Context.DeclarationNames.getCXXDestructorName( Context.getCanonicalType(ClassType)); if (NewFD->getDeclName() != Name) { Diag(NewFD->getLocation(), diag::err_destructor_name); NewFD->setInvalidDecl(); return Redeclaration; } } } else if (CXXConversionDecl *Conversion = dyn_cast(NewFD)) { ActOnConversionDeclarator(Conversion); } else if (auto *Guide = dyn_cast(NewFD)) { if (auto *TD = Guide->getDescribedFunctionTemplate()) CheckDeductionGuideTemplate(TD); // A deduction guide is not on the list of entities that can be // explicitly specialized. if (Guide->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) Diag(Guide->getLocStart(), diag::err_deduction_guide_specialized) << /*explicit specialization*/ 1; } // Find any virtual functions that this function overrides. if (CXXMethodDecl *Method = dyn_cast(NewFD)) { if (!Method->isFunctionTemplateSpecialization() && !Method->getDescribedFunctionTemplate() && Method->isCanonicalDecl()) { if (AddOverriddenMethods(Method->getParent(), Method)) { // If the function was marked as "static", we have a problem. if (NewFD->getStorageClass() == SC_Static) { ReportOverrides(*this, diag::err_static_overrides_virtual, Method); } } } if (Method->isStatic()) checkThisInStaticMemberFunctionType(Method); } // Extra checking for C++ overloaded operators (C++ [over.oper]). if (NewFD->isOverloadedOperator() && CheckOverloadedOperatorDeclaration(NewFD)) { NewFD->setInvalidDecl(); return Redeclaration; } // Extra checking for C++0x literal operators (C++0x [over.literal]). if (NewFD->getLiteralIdentifier() && CheckLiteralOperatorDeclaration(NewFD)) { NewFD->setInvalidDecl(); return Redeclaration; } // In C++, check default arguments now that we have merged decls. Unless // the lexical context is the class, because in this case this is done // during delayed parsing anyway. if (!CurContext->isRecord()) CheckCXXDefaultArguments(NewFD); // If this function declares a builtin function, check the type of this // declaration against the expected type for the builtin. if (unsigned BuiltinID = NewFD->getBuiltinID()) { ASTContext::GetBuiltinTypeError Error; LookupPredefedObjCSuperType(*this, S, NewFD->getIdentifier()); QualType T = Context.GetBuiltinType(BuiltinID, Error); // If the type of the builtin differs only in its exception // specification, that's OK. // FIXME: If the types do differ in this way, it would be better to // retain the 'noexcept' form of the type. if (!T.isNull() && !Context.hasSameFunctionTypeIgnoringExceptionSpec(T, NewFD->getType())) // The type of this function differs from the type of the builtin, // so forget about the builtin entirely. Context.BuiltinInfo.forgetBuiltin(BuiltinID, Context.Idents); } // If this function is declared as being extern "C", then check to see if // the function returns a UDT (class, struct, or union type) that is not C // compatible, and if it does, warn the user. // But, issue any diagnostic on the first declaration only. if (Previous.empty() && NewFD->isExternC()) { QualType R = NewFD->getReturnType(); if (R->isIncompleteType() && !R->isVoidType()) Diag(NewFD->getLocation(), diag::warn_return_value_udt_incomplete) << NewFD << R; else if (!R.isPODType(Context) && !R->isVoidType() && !R->isObjCObjectPointerType()) Diag(NewFD->getLocation(), diag::warn_return_value_udt) << NewFD << R; } // C++1z [dcl.fct]p6: // [...] whether the function has a non-throwing exception-specification // [is] part of the function type // // This results in an ABI break between C++14 and C++17 for functions whose // declared type includes an exception-specification in a parameter or // return type. (Exception specifications on the function itself are OK in // most cases, and exception specifications are not permitted in most other // contexts where they could make it into a mangling.) if (!getLangOpts().CPlusPlus1z && !NewFD->getPrimaryTemplate()) { auto HasNoexcept = [&](QualType T) -> bool { // Strip off declarator chunks that could be between us and a function // type. We don't need to look far, exception specifications are very // restricted prior to C++17. if (auto *RT = T->getAs()) T = RT->getPointeeType(); else if (T->isAnyPointerType()) T = T->getPointeeType(); else if (auto *MPT = T->getAs()) T = MPT->getPointeeType(); if (auto *FPT = T->getAs()) if (FPT->isNothrow(Context)) return true; return false; }; auto *FPT = NewFD->getType()->castAs(); bool AnyNoexcept = HasNoexcept(FPT->getReturnType()); for (QualType T : FPT->param_types()) AnyNoexcept |= HasNoexcept(T); if (AnyNoexcept) Diag(NewFD->getLocation(), diag::warn_cxx1z_compat_exception_spec_in_signature) << NewFD; } if (!Redeclaration && LangOpts.CUDA) checkCUDATargetOverload(NewFD, Previous); } return Redeclaration; } void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { // C++11 [basic.start.main]p3: // A program that [...] declares main to be inline, static or // constexpr is ill-formed. // C11 6.7.4p4: In a hosted environment, no function specifier(s) shall // appear in a declaration of main. // static main is not an error under C99, but we should warn about it. // We accept _Noreturn main as an extension. if (FD->getStorageClass() == SC_Static) Diag(DS.getStorageClassSpecLoc(), getLangOpts().CPlusPlus ? diag::err_static_main : diag::warn_static_main) << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc()); if (FD->isInlineSpecified()) Diag(DS.getInlineSpecLoc(), diag::err_inline_main) << FixItHint::CreateRemoval(DS.getInlineSpecLoc()); if (DS.isNoreturnSpecified()) { SourceLocation NoreturnLoc = DS.getNoreturnSpecLoc(); SourceRange NoreturnRange(NoreturnLoc, getLocForEndOfToken(NoreturnLoc)); Diag(NoreturnLoc, diag::ext_noreturn_main); Diag(NoreturnLoc, diag::note_main_remove_noreturn) << FixItHint::CreateRemoval(NoreturnRange); } if (FD->isConstexpr()) { Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_main) << FixItHint::CreateRemoval(DS.getConstexprSpecLoc()); FD->setConstexpr(false); } if (getLangOpts().OpenCL) { Diag(FD->getLocation(), diag::err_opencl_no_main) << FD->hasAttr(); FD->setInvalidDecl(); return; } QualType T = FD->getType(); assert(T->isFunctionType() && "function decl is not of function type"); const FunctionType* FT = T->castAs(); if (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) { // In C with GNU extensions we allow main() to have non-integer return // type, but we should warn about the extension, and we disable the // implicit-return-zero rule. // GCC in C mode accepts qualified 'int'. if (Context.hasSameUnqualifiedType(FT->getReturnType(), Context.IntTy)) FD->setHasImplicitReturnZero(true); else { Diag(FD->getTypeSpecStartLoc(), diag::ext_main_returns_nonint); SourceRange RTRange = FD->getReturnTypeSourceRange(); if (RTRange.isValid()) Diag(RTRange.getBegin(), diag::note_main_change_return_type) << FixItHint::CreateReplacement(RTRange, "int"); } } else { // In C and C++, main magically returns 0 if you fall off the end; // set the flag which tells us that. // This is C++ [basic.start.main]p5 and C99 5.1.2.2.3. // All the standards say that main() should return 'int'. if (Context.hasSameType(FT->getReturnType(), Context.IntTy)) FD->setHasImplicitReturnZero(true); else { // Otherwise, this is just a flat-out error. SourceRange RTRange = FD->getReturnTypeSourceRange(); Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint) << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "int") : FixItHint()); FD->setInvalidDecl(true); } } // Treat protoless main() as nullary. if (isa(FT)) return; const FunctionProtoType* FTP = cast(FT); unsigned nparams = FTP->getNumParams(); assert(FD->getNumParams() == nparams); bool HasExtraParameters = (nparams > 3); if (FTP->isVariadic()) { Diag(FD->getLocation(), diag::ext_variadic_main); // FIXME: if we had information about the location of the ellipsis, we // could add a FixIt hint to remove it as a parameter. } // Darwin passes an undocumented fourth argument of type char**. If // other platforms start sprouting these, the logic below will start // getting shifty. if (nparams == 4 && Context.getTargetInfo().getTriple().isOSDarwin()) HasExtraParameters = false; if (HasExtraParameters) { Diag(FD->getLocation(), diag::err_main_surplus_args) << nparams; FD->setInvalidDecl(true); nparams = 3; } // FIXME: a lot of the following diagnostics would be improved // if we had some location information about types. QualType CharPP = Context.getPointerType(Context.getPointerType(Context.CharTy)); QualType Expected[] = { Context.IntTy, CharPP, CharPP, CharPP }; for (unsigned i = 0; i < nparams; ++i) { QualType AT = FTP->getParamType(i); bool mismatch = true; if (Context.hasSameUnqualifiedType(AT, Expected[i])) mismatch = false; else if (Expected[i] == CharPP) { // As an extension, the following forms are okay: // char const ** // char const * const * // char * const * QualifierCollector qs; const PointerType* PT; if ((PT = qs.strip(AT)->getAs()) && (PT = qs.strip(PT->getPointeeType())->getAs()) && Context.hasSameType(QualType(qs.strip(PT->getPointeeType()), 0), Context.CharTy)) { qs.removeConst(); mismatch = !qs.empty(); } } if (mismatch) { Diag(FD->getLocation(), diag::err_main_arg_wrong) << i << Expected[i]; // TODO: suggest replacing given type with expected type FD->setInvalidDecl(true); } } if (nparams == 1 && !FD->isInvalidDecl()) { Diag(FD->getLocation(), diag::warn_main_one_arg); } if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) { Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD; FD->setInvalidDecl(); } } void Sema::CheckMSVCRTEntryPoint(FunctionDecl *FD) { QualType T = FD->getType(); assert(T->isFunctionType() && "function decl is not of function type"); const FunctionType *FT = T->castAs(); // Set an implicit return of 'zero' if the function can return some integral, // enumeration, pointer or nullptr type. if (FT->getReturnType()->isIntegralOrEnumerationType() || FT->getReturnType()->isAnyPointerType() || FT->getReturnType()->isNullPtrType()) // DllMain is exempt because a return value of zero means it failed. if (FD->getName() != "DllMain") FD->setHasImplicitReturnZero(true); if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) { Diag(FD->getLocation(), diag::err_mainlike_template_decl) << FD; FD->setInvalidDecl(); } } bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) { // FIXME: Need strict checking. In C89, we need to check for // any assignment, increment, decrement, function-calls, or // commas outside of a sizeof. In C99, it's the same list, // except that the aforementioned are allowed in unevaluated // expressions. Everything else falls under the // "may accept other forms of constant expressions" exception. // (We never end up here for C++, so the constant expression // rules there don't matter.) const Expr *Culprit; if (Init->isConstantInitializer(Context, false, &Culprit)) return false; Diag(Culprit->getExprLoc(), diag::err_init_element_not_constant) << Culprit->getSourceRange(); return true; } namespace { // Visits an initialization expression to see if OrigDecl is evaluated in // its own initialization and throws a warning if it does. class SelfReferenceChecker : public EvaluatedExprVisitor { Sema &S; Decl *OrigDecl; bool isRecordType; bool isPODType; bool isReferenceType; bool isInitList; llvm::SmallVector InitFieldIndex; public: typedef EvaluatedExprVisitor Inherited; SelfReferenceChecker(Sema &S, Decl *OrigDecl) : Inherited(S.Context), S(S), OrigDecl(OrigDecl) { isPODType = false; isRecordType = false; isReferenceType = false; isInitList = false; if (ValueDecl *VD = dyn_cast(OrigDecl)) { isPODType = VD->getType().isPODType(S.Context); isRecordType = VD->getType()->isRecordType(); isReferenceType = VD->getType()->isReferenceType(); } } // For most expressions, just call the visitor. For initializer lists, // track the index of the field being initialized since fields are // initialized in order allowing use of previously initialized fields. void CheckExpr(Expr *E) { InitListExpr *InitList = dyn_cast(E); if (!InitList) { Visit(E); return; } // Track and increment the index here. isInitList = true; InitFieldIndex.push_back(0); for (auto Child : InitList->children()) { CheckExpr(cast(Child)); ++InitFieldIndex.back(); } InitFieldIndex.pop_back(); } // Returns true if MemberExpr is checked and no further checking is needed. // Returns false if additional checking is required. bool CheckInitListMemberExpr(MemberExpr *E, bool CheckReference) { llvm::SmallVector Fields; Expr *Base = E; bool ReferenceField = false; // Get the field memebers used. while (MemberExpr *ME = dyn_cast(Base)) { FieldDecl *FD = dyn_cast(ME->getMemberDecl()); if (!FD) return false; Fields.push_back(FD); if (FD->getType()->isReferenceType()) ReferenceField = true; Base = ME->getBase()->IgnoreParenImpCasts(); } // Keep checking only if the base Decl is the same. DeclRefExpr *DRE = dyn_cast(Base); if (!DRE || DRE->getDecl() != OrigDecl) return false; // A reference field can be bound to an unininitialized field. if (CheckReference && !ReferenceField) return true; // Convert FieldDecls to their index number. llvm::SmallVector UsedFieldIndex; for (const FieldDecl *I : llvm::reverse(Fields)) UsedFieldIndex.push_back(I->getFieldIndex()); // See if a warning is needed by checking the first difference in index // numbers. If field being used has index less than the field being // initialized, then the use is safe. for (auto UsedIter = UsedFieldIndex.begin(), UsedEnd = UsedFieldIndex.end(), OrigIter = InitFieldIndex.begin(), OrigEnd = InitFieldIndex.end(); UsedIter != UsedEnd && OrigIter != OrigEnd; ++UsedIter, ++OrigIter) { if (*UsedIter < *OrigIter) return true; if (*UsedIter > *OrigIter) break; } // TODO: Add a different warning which will print the field names. HandleDeclRefExpr(DRE); return true; } // For most expressions, the cast is directly above the DeclRefExpr. // For conditional operators, the cast can be outside the conditional // operator if both expressions are DeclRefExpr's. void HandleValue(Expr *E) { E = E->IgnoreParens(); if (DeclRefExpr* DRE = dyn_cast(E)) { HandleDeclRefExpr(DRE); return; } if (ConditionalOperator *CO = dyn_cast(E)) { Visit(CO->getCond()); HandleValue(CO->getTrueExpr()); HandleValue(CO->getFalseExpr()); return; } if (BinaryConditionalOperator *BCO = dyn_cast(E)) { Visit(BCO->getCond()); HandleValue(BCO->getFalseExpr()); return; } if (OpaqueValueExpr *OVE = dyn_cast(E)) { HandleValue(OVE->getSourceExpr()); return; } if (BinaryOperator *BO = dyn_cast(E)) { if (BO->getOpcode() == BO_Comma) { Visit(BO->getLHS()); HandleValue(BO->getRHS()); return; } } if (isa(E)) { if (isInitList) { if (CheckInitListMemberExpr(cast(E), false /*CheckReference*/)) return; } Expr *Base = E->IgnoreParenImpCasts(); while (MemberExpr *ME = dyn_cast(Base)) { // Check for static member variables and don't warn on them. if (!isa(ME->getMemberDecl())) return; Base = ME->getBase()->IgnoreParenImpCasts(); } if (DeclRefExpr *DRE = dyn_cast(Base)) HandleDeclRefExpr(DRE); return; } Visit(E); } // Reference types not handled in HandleValue are handled here since all // uses of references are bad, not just r-value uses. void VisitDeclRefExpr(DeclRefExpr *E) { if (isReferenceType) HandleDeclRefExpr(E); } void VisitImplicitCastExpr(ImplicitCastExpr *E) { if (E->getCastKind() == CK_LValueToRValue) { HandleValue(E->getSubExpr()); return; } Inherited::VisitImplicitCastExpr(E); } void VisitMemberExpr(MemberExpr *E) { if (isInitList) { if (CheckInitListMemberExpr(E, true /*CheckReference*/)) return; } // Don't warn on arrays since they can be treated as pointers. if (E->getType()->canDecayToPointerType()) return; // Warn when a non-static method call is followed by non-static member // field accesses, which is followed by a DeclRefExpr. CXXMethodDecl *MD = dyn_cast(E->getMemberDecl()); bool Warn = (MD && !MD->isStatic()); Expr *Base = E->getBase()->IgnoreParenImpCasts(); while (MemberExpr *ME = dyn_cast(Base)) { if (!isa(ME->getMemberDecl())) Warn = false; Base = ME->getBase()->IgnoreParenImpCasts(); } if (DeclRefExpr *DRE = dyn_cast(Base)) { if (Warn) HandleDeclRefExpr(DRE); return; } // The base of a MemberExpr is not a MemberExpr or a DeclRefExpr. // Visit that expression. Visit(Base); } void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { Expr *Callee = E->getCallee(); if (isa(Callee)) return Inherited::VisitCXXOperatorCallExpr(E); Visit(Callee); for (auto Arg: E->arguments()) HandleValue(Arg->IgnoreParenImpCasts()); } void VisitUnaryOperator(UnaryOperator *E) { // For POD record types, addresses of its own members are well-defined. if (E->getOpcode() == UO_AddrOf && isRecordType && isa(E->getSubExpr()->IgnoreParens())) { if (!isPODType) HandleValue(E->getSubExpr()); return; } if (E->isIncrementDecrementOp()) { HandleValue(E->getSubExpr()); return; } Inherited::VisitUnaryOperator(E); } void VisitObjCMessageExpr(ObjCMessageExpr *E) {} void VisitCXXConstructExpr(CXXConstructExpr *E) { if (E->getConstructor()->isCopyConstructor()) { Expr *ArgExpr = E->getArg(0); if (InitListExpr *ILE = dyn_cast(ArgExpr)) if (ILE->getNumInits() == 1) ArgExpr = ILE->getInit(0); if (ImplicitCastExpr *ICE = dyn_cast(ArgExpr)) if (ICE->getCastKind() == CK_NoOp) ArgExpr = ICE->getSubExpr(); HandleValue(ArgExpr); return; } Inherited::VisitCXXConstructExpr(E); } void VisitCallExpr(CallExpr *E) { // Treat std::move as a use. if (E->getNumArgs() == 1) { if (FunctionDecl *FD = E->getDirectCallee()) { if (FD->isInStdNamespace() && FD->getIdentifier() && FD->getIdentifier()->isStr("move")) { HandleValue(E->getArg(0)); return; } } } Inherited::VisitCallExpr(E); } void VisitBinaryOperator(BinaryOperator *E) { if (E->isCompoundAssignmentOp()) { HandleValue(E->getLHS()); Visit(E->getRHS()); return; } Inherited::VisitBinaryOperator(E); } // A custom visitor for BinaryConditionalOperator is needed because the // regular visitor would check the condition and true expression separately // but both point to the same place giving duplicate diagnostics. void VisitBinaryConditionalOperator(BinaryConditionalOperator *E) { Visit(E->getCond()); Visit(E->getFalseExpr()); } void HandleDeclRefExpr(DeclRefExpr *DRE) { Decl* ReferenceDecl = DRE->getDecl(); if (OrigDecl != ReferenceDecl) return; unsigned diag; if (isReferenceType) { diag = diag::warn_uninit_self_reference_in_reference_init; } else if (cast(OrigDecl)->isStaticLocal()) { diag = diag::warn_static_self_reference_in_init; } else if (isa(OrigDecl->getDeclContext()) || isa(OrigDecl->getDeclContext()) || DRE->getDecl()->getType()->isRecordType()) { diag = diag::warn_uninit_self_reference_in_init; } else { // Local variables will be handled by the CFG analysis. return; } S.DiagRuntimeBehavior(DRE->getLocStart(), DRE, S.PDiag(diag) << DRE->getNameInfo().getName() << OrigDecl->getLocation() << DRE->getSourceRange()); } }; /// CheckSelfReference - Warns if OrigDecl is used in expression E. static void CheckSelfReference(Sema &S, Decl* OrigDecl, Expr *E, bool DirectInit) { // Parameters arguments are occassionially constructed with itself, // for instance, in recursive functions. Skip them. if (isa(OrigDecl)) return; E = E->IgnoreParens(); // Skip checking T a = a where T is not a record or reference type. // Doing so is a way to silence uninitialized warnings. if (!DirectInit && !cast(OrigDecl)->getType()->isRecordType()) if (ImplicitCastExpr *ICE = dyn_cast(E)) if (ICE->getCastKind() == CK_LValueToRValue) if (DeclRefExpr *DRE = dyn_cast(ICE->getSubExpr())) if (DRE->getDecl() == OrigDecl) return; SelfReferenceChecker(S, OrigDecl).CheckExpr(E); } } // end anonymous namespace namespace { // Simple wrapper to add the name of a variable or (if no variable is // available) a DeclarationName into a diagnostic. struct VarDeclOrName { VarDecl *VDecl; DeclarationName Name; friend const Sema::SemaDiagnosticBuilder & operator<<(const Sema::SemaDiagnosticBuilder &Diag, VarDeclOrName VN) { return VN.VDecl ? Diag << VN.VDecl : Diag << VN.Name; } }; } // end anonymous namespace QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name, QualType Type, TypeSourceInfo *TSI, SourceRange Range, bool DirectInit, Expr *Init) { bool IsInitCapture = !VDecl; assert((!VDecl || !VDecl->isInitCapture()) && "init captures are expected to be deduced prior to initialization"); VarDeclOrName VN{VDecl, Name}; DeducedType *Deduced = Type->getContainedDeducedType(); assert(Deduced && "deduceVarTypeFromInitializer for non-deduced type"); // C++11 [dcl.spec.auto]p3 if (!Init) { assert(VDecl && "no init for init capture deduction?"); Diag(VDecl->getLocation(), diag::err_auto_var_requires_init) << VDecl->getDeclName() << Type; return QualType(); } ArrayRef DeduceInits = Init; if (DirectInit) { if (auto *PL = dyn_cast_or_null(Init)) DeduceInits = PL->exprs(); } if (isa(Deduced)) { assert(VDecl && "non-auto type for init capture deduction?"); InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); InitializationKind Kind = InitializationKind::CreateForInit( VDecl->getLocation(), DirectInit, Init); // FIXME: Initialization should not be taking a mutable list of inits. SmallVector InitsCopy(DeduceInits.begin(), DeduceInits.end()); return DeduceTemplateSpecializationFromInitializer(TSI, Entity, Kind, InitsCopy); } if (DirectInit) { if (auto *IL = dyn_cast(Init)) DeduceInits = IL->inits(); } // Deduction only works if we have exactly one source expression. if (DeduceInits.empty()) { // It isn't possible to write this directly, but it is possible to // end up in this situation with "auto x(some_pack...);" Diag(Init->getLocStart(), IsInitCapture ? diag::err_init_capture_no_expression : diag::err_auto_var_init_no_expression) << VN << Type << Range; return QualType(); } if (DeduceInits.size() > 1) { Diag(DeduceInits[1]->getLocStart(), IsInitCapture ? diag::err_init_capture_multiple_expressions : diag::err_auto_var_init_multiple_expressions) << VN << Type << Range; return QualType(); } Expr *DeduceInit = DeduceInits[0]; if (DirectInit && isa(DeduceInit)) { Diag(Init->getLocStart(), IsInitCapture ? diag::err_init_capture_paren_braces : diag::err_auto_var_init_paren_braces) << isa(Init) << VN << Type << Range; return QualType(); } // Expressions default to 'id' when we're in a debugger. bool DefaultedAnyToId = false; if (getLangOpts().DebuggerCastResultToId && Init->getType() == Context.UnknownAnyTy && !IsInitCapture) { ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType()); if (Result.isInvalid()) { return QualType(); } Init = Result.get(); DefaultedAnyToId = true; } // C++ [dcl.decomp]p1: // If the assignment-expression [...] has array type A and no ref-qualifier // is present, e has type cv A if (VDecl && isa(VDecl) && Context.hasSameUnqualifiedType(Type, Context.getAutoDeductType()) && DeduceInit->getType()->isConstantArrayType()) return Context.getQualifiedType(DeduceInit->getType(), Type.getQualifiers()); QualType DeducedType; if (DeduceAutoType(TSI, DeduceInit, DeducedType) == DAR_Failed) { if (!IsInitCapture) DiagnoseAutoDeductionFailure(VDecl, DeduceInit); else if (isa(Init)) Diag(Range.getBegin(), diag::err_init_capture_deduction_failure_from_init_list) << VN << (DeduceInit->getType().isNull() ? TSI->getType() : DeduceInit->getType()) << DeduceInit->getSourceRange(); else Diag(Range.getBegin(), diag::err_init_capture_deduction_failure) << VN << TSI->getType() << (DeduceInit->getType().isNull() ? TSI->getType() : DeduceInit->getType()) << DeduceInit->getSourceRange(); } // Warn if we deduced 'id'. 'auto' usually implies type-safety, but using // 'id' instead of a specific object type prevents most of our usual // checks. // We only want to warn outside of template instantiations, though: // inside a template, the 'id' could have come from a parameter. if (!inTemplateInstantiation() && !DefaultedAnyToId && !IsInitCapture && !DeducedType.isNull() && DeducedType->isObjCIdType()) { SourceLocation Loc = TSI->getTypeLoc().getBeginLoc(); Diag(Loc, diag::warn_auto_var_is_id) << VN << Range; } return DeducedType; } bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, Expr *Init) { QualType DeducedType = deduceVarTypeFromInitializer( VDecl, VDecl->getDeclName(), VDecl->getType(), VDecl->getTypeSourceInfo(), VDecl->getSourceRange(), DirectInit, Init); if (DeducedType.isNull()) { VDecl->setInvalidDecl(); return true; } VDecl->setType(DeducedType); assert(VDecl->isLinkageValid()); // In ARC, infer lifetime. if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl)) VDecl->setInvalidDecl(); // If this is a redeclaration, check that the type we just deduced matches // the previously declared type. if (VarDecl *Old = VDecl->getPreviousDecl()) { // We never need to merge the type, because we cannot form an incomplete // array of auto, nor deduce such a type. MergeVarDeclTypes(VDecl, Old, /*MergeTypeWithPrevious*/ false); } // Check the deduced type is valid for a variable declaration. CheckVariableDeclarationType(VDecl); return VDecl->isInvalidDecl(); } /// AddInitializerToDecl - Adds the initializer Init to the /// declaration dcl. If DirectInit is true, this is C++ direct /// initialization rather than copy initialization. void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // If there is no declaration, there was an error parsing it. Just ignore // the initializer. if (!RealDecl || RealDecl->isInvalidDecl()) { CorrectDelayedTyposInExpr(Init, dyn_cast_or_null(RealDecl)); return; } if (CXXMethodDecl *Method = dyn_cast(RealDecl)) { // Pure-specifiers are handled in ActOnPureSpecifier. Diag(Method->getLocation(), diag::err_member_function_initialization) << Method->getDeclName() << Init->getSourceRange(); Method->setInvalidDecl(); return; } VarDecl *VDecl = dyn_cast(RealDecl); if (!VDecl) { assert(!isa(RealDecl) && "field init shouldn't get here"); Diag(RealDecl->getLocation(), diag::err_illegal_initializer); RealDecl->setInvalidDecl(); return; } // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (VDecl->getType()->isUndeducedType()) { // Attempt typo correction early so that the type of the init expression can // be deduced based on the chosen correction if the original init contains a // TypoExpr. ExprResult Res = CorrectDelayedTyposInExpr(Init, VDecl); if (!Res.isUsable()) { RealDecl->setInvalidDecl(); return; } Init = Res.get(); if (DeduceVariableDeclarationType(VDecl, DirectInit, Init)) return; } // dllimport cannot be used on variable definitions. if (VDecl->hasAttr() && !VDecl->isStaticDataMember()) { Diag(VDecl->getLocation(), diag::err_attribute_dllimport_data_definition); VDecl->setInvalidDecl(); return; } if (VDecl->isLocalVarDecl() && VDecl->hasExternalStorage()) { // C99 6.7.8p5. C++ has no such restriction, but that is a defect. Diag(VDecl->getLocation(), diag::err_block_extern_cant_init); VDecl->setInvalidDecl(); return; } if (!VDecl->getType()->isDependentType()) { // A definition must end up with a complete type, which means it must be // complete with the restriction that an array type might be completed by // the initializer; note that later code assumes this restriction. QualType BaseDeclType = VDecl->getType(); if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType)) BaseDeclType = Array->getElementType(); if (RequireCompleteType(VDecl->getLocation(), BaseDeclType, diag::err_typecheck_decl_incomplete_type)) { RealDecl->setInvalidDecl(); return; } // The variable can not have an abstract class type. if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(), diag::err_abstract_type_in_decl, AbstractVariableType)) VDecl->setInvalidDecl(); } // If adding the initializer will turn this declaration into a definition, // and we already have a definition for this variable, diagnose or otherwise // handle the situation. VarDecl *Def; if ((Def = VDecl->getDefinition()) && Def != VDecl && (!VDecl->isStaticDataMember() || VDecl->isOutOfLine()) && !VDecl->isThisDeclarationADemotedDefinition() && checkVarDeclRedefinition(Def, VDecl)) return; if (getLangOpts().CPlusPlus) { // C++ [class.static.data]p4 // If a static data member is of const integral or const // enumeration type, its declaration in the class definition can // specify a constant-initializer which shall be an integral // constant expression (5.19). In that case, the member can appear // in integral constant expressions. The member shall still be // defined in a namespace scope if it is used in the program and the // namespace scope definition shall not contain an initializer. // // We already performed a redefinition check above, but for static // data members we also need to check whether there was an in-class // declaration with an initializer. if (VDecl->isStaticDataMember() && VDecl->getCanonicalDecl()->hasInit()) { Diag(Init->getExprLoc(), diag::err_static_data_member_reinitialization) << VDecl->getDeclName(); Diag(VDecl->getCanonicalDecl()->getInit()->getExprLoc(), diag::note_previous_initializer) << 0; return; } if (VDecl->hasLocalStorage()) getCurFunction()->setHasBranchProtectedScope(); if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) { VDecl->setInvalidDecl(); return; } } // OpenCL 1.1 6.5.2: "Variables allocated in the __local address space inside // a kernel function cannot be initialized." if (VDecl->getType().getAddressSpace() == LangAS::opencl_local) { Diag(VDecl->getLocation(), diag::err_local_cant_init); VDecl->setInvalidDecl(); return; } // Get the decls type and save a reference for later, since // CheckInitializerTypes may change it. QualType DclT = VDecl->getType(), SavT = DclT; // Expressions default to 'id' when we're in a debugger // and we are assigning it to a variable of Objective-C pointer type. if (getLangOpts().DebuggerCastResultToId && DclT->isObjCObjectPointerType() && Init->getType() == Context.UnknownAnyTy) { ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType()); if (Result.isInvalid()) { VDecl->setInvalidDecl(); return; } Init = Result.get(); } // Perform the initialization. ParenListExpr *CXXDirectInit = dyn_cast(Init); if (!VDecl->isInvalidDecl()) { InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); InitializationKind Kind = InitializationKind::CreateForInit( VDecl->getLocation(), DirectInit, Init); MultiExprArg Args = Init; if (CXXDirectInit) Args = MultiExprArg(CXXDirectInit->getExprs(), CXXDirectInit->getNumExprs()); // Try to correct any TypoExprs in the initialization arguments. for (size_t Idx = 0; Idx < Args.size(); ++Idx) { ExprResult Res = CorrectDelayedTyposInExpr( Args[Idx], VDecl, [this, Entity, Kind](Expr *E) { InitializationSequence Init(*this, Entity, Kind, MultiExprArg(E)); return Init.Failed() ? ExprError() : E; }); if (Res.isInvalid()) { VDecl->setInvalidDecl(); } else if (Res.get() != Args[Idx]) { Args[Idx] = Res.get(); } } if (VDecl->isInvalidDecl()) return; InitializationSequence InitSeq(*this, Entity, Kind, Args, /*TopLevelOfInitList=*/false, /*TreatUnavailableAsInvalid=*/false); ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT); if (Result.isInvalid()) { VDecl->setInvalidDecl(); return; } Init = Result.getAs(); } // Check for self-references within variable initializers. // Variables declared within a function/method body (except for references) // are handled by a dataflow analysis. if (!VDecl->hasLocalStorage() || VDecl->getType()->isRecordType() || VDecl->getType()->isReferenceType()) { CheckSelfReference(*this, RealDecl, Init, DirectInit); } // If the type changed, it means we had an incomplete type that was // completed by the initializer. For example: // int ary[] = { 1, 3, 5 }; // "ary" transitions from an IncompleteArrayType to a ConstantArrayType. if (!VDecl->isInvalidDecl() && (DclT != SavT)) VDecl->setType(DclT); if (!VDecl->isInvalidDecl()) { checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init); if (VDecl->hasAttr()) checkRetainCycles(VDecl, Init); // It is safe to assign a weak reference into a strong variable. // Although this code can still have problems: // id x = self.weakProp; // id y = self.weakProp; // we do not warn to warn spuriously when 'x' and 'y' are on separate // paths through the function. This should be revisited if // -Wrepeated-use-of-weak is made flow-sensitive. if ((VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong || VDecl->getType().isNonWeakInMRRWithObjCWeak(Context)) && !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Init->getLocStart())) getCurFunction()->markSafeWeakUse(Init); } // The initialization is usually a full-expression. // // FIXME: If this is a braced initialization of an aggregate, it is not // an expression, and each individual field initializer is a separate // full-expression. For instance, in: // // struct Temp { ~Temp(); }; // struct S { S(Temp); }; // struct T { S a, b; } t = { Temp(), Temp() } // // we should destroy the first Temp before constructing the second. ExprResult Result = ActOnFinishFullExpr(Init, VDecl->getLocation(), false, VDecl->isConstexpr()); if (Result.isInvalid()) { VDecl->setInvalidDecl(); return; } Init = Result.get(); // Attach the initializer to the decl. VDecl->setInit(Init); if (VDecl->isLocalVarDecl()) { // Don't check the initializer if the declaration is malformed. if (VDecl->isInvalidDecl()) { // do nothing // OpenCL v1.2 s6.5.3: __constant locals must be constant-initialized. // This is true even in OpenCL C++. } else if (VDecl->getType().getAddressSpace() == LangAS::opencl_constant) { CheckForConstantInitializer(Init, DclT); // Otherwise, C++ does not restrict the initializer. } else if (getLangOpts().CPlusPlus) { // do nothing // C99 6.7.8p4: All the expressions in an initializer for an object that has // static storage duration shall be constant expressions or string literals. } else if (VDecl->getStorageClass() == SC_Static) { CheckForConstantInitializer(Init, DclT); // C89 is stricter than C99 for aggregate initializers. // C89 6.5.7p3: All the expressions [...] in an initializer list // for an object that has aggregate or union type shall be // constant expressions. } else if (!getLangOpts().C99 && VDecl->getType()->isAggregateType() && isa(Init)) { const Expr *Culprit; if (!Init->isConstantInitializer(Context, false, &Culprit)) { Diag(Culprit->getExprLoc(), diag::ext_aggregate_init_not_constant) << Culprit->getSourceRange(); } } } else if (VDecl->isStaticDataMember() && !VDecl->isInline() && VDecl->getLexicalDeclContext()->isRecord()) { // This is an in-class initialization for a static data member, e.g., // // struct S { // static const int value = 17; // }; // C++ [class.mem]p4: // A member-declarator can contain a constant-initializer only // if it declares a static member (9.4) of const integral or // const enumeration type, see 9.4.2. // // C++11 [class.static.data]p3: // If a non-volatile non-inline const static data member is of integral // or enumeration type, its declaration in the class definition can // specify a brace-or-equal-initializer in which every initializer-clause // that is an assignment-expression is a constant expression. A static // data member of literal type can be declared in the class definition // with the constexpr specifier; if so, its declaration shall specify a // brace-or-equal-initializer in which every initializer-clause that is // an assignment-expression is a constant expression. // Do nothing on dependent types. if (DclT->isDependentType()) { // Allow any 'static constexpr' members, whether or not they are of literal // type. We separately check that every constexpr variable is of literal // type. } else if (VDecl->isConstexpr()) { // Require constness. } else if (!DclT.isConstQualified()) { Diag(VDecl->getLocation(), diag::err_in_class_initializer_non_const) << Init->getSourceRange(); VDecl->setInvalidDecl(); // We allow integer constant expressions in all cases. } else if (DclT->isIntegralOrEnumerationType()) { // Check whether the expression is a constant expression. SourceLocation Loc; if (getLangOpts().CPlusPlus11 && DclT.isVolatileQualified()) // In C++11, a non-constexpr const static data member with an // in-class initializer cannot be volatile. Diag(VDecl->getLocation(), diag::err_in_class_initializer_volatile); else if (Init->isValueDependent()) ; // Nothing to check. else if (Init->isIntegerConstantExpr(Context, &Loc)) ; // Ok, it's an ICE! else if (Init->isEvaluatable(Context)) { // If we can constant fold the initializer through heroics, accept it, // but report this as a use of an extension for -pedantic. Diag(Loc, diag::ext_in_class_initializer_non_constant) << Init->getSourceRange(); } else { // Otherwise, this is some crazy unknown case. Report the issue at the // location provided by the isIntegerConstantExpr failed check. Diag(Loc, diag::err_in_class_initializer_non_constant) << Init->getSourceRange(); VDecl->setInvalidDecl(); } // We allow foldable floating-point constants as an extension. } else if (DclT->isFloatingType()) { // also permits complex, which is ok // In C++98, this is a GNU extension. In C++11, it is not, but we support // it anyway and provide a fixit to add the 'constexpr'. if (getLangOpts().CPlusPlus11) { Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type_cxx11) << DclT << Init->getSourceRange(); Diag(VDecl->getLocStart(), diag::note_in_class_initializer_float_type_cxx11) << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); } else { Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type) << DclT << Init->getSourceRange(); if (!Init->isValueDependent() && !Init->isEvaluatable(Context)) { Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant) << Init->getSourceRange(); VDecl->setInvalidDecl(); } } // Suggest adding 'constexpr' in C++11 for literal types. } else if (getLangOpts().CPlusPlus11 && DclT->isLiteralType(Context)) { Diag(VDecl->getLocation(), diag::err_in_class_initializer_literal_type) << DclT << Init->getSourceRange() << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); VDecl->setConstexpr(true); } else { Diag(VDecl->getLocation(), diag::err_in_class_initializer_bad_type) << DclT << Init->getSourceRange(); VDecl->setInvalidDecl(); } } else if (VDecl->isFileVarDecl()) { // In C, extern is typically used to avoid tentative definitions when // declaring variables in headers, but adding an intializer makes it a // defintion. This is somewhat confusing, so GCC and Clang both warn on it. // In C++, extern is often used to give implictly static const variables // external linkage, so don't warn in that case. If selectany is present, // this might be header code intended for C and C++ inclusion, so apply the // C++ rules. if (VDecl->getStorageClass() == SC_Extern && ((!getLangOpts().CPlusPlus && !VDecl->hasAttr()) || !Context.getBaseElementType(VDecl->getType()).isConstQualified()) && !(getLangOpts().CPlusPlus && VDecl->isExternC()) && !isTemplateInstantiation(VDecl->getTemplateSpecializationKind())) Diag(VDecl->getLocation(), diag::warn_extern_init); // C99 6.7.8p4. All file scoped initializers need to be constant. if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl()) CheckForConstantInitializer(Init, DclT); } // We will represent direct-initialization similarly to copy-initialization: // int x(1); -as-> int x = 1; // ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c); // // Clients that want to distinguish between the two forms, can check for // direct initializer using VarDecl::getInitStyle(). // A major benefit is that clients that don't particularly care about which // exactly form was it (like the CodeGen) can handle both cases without // special case code. // C++ 8.5p11: // The form of initialization (using parentheses or '=') is generally // insignificant, but does matter when the entity being initialized has a // class type. if (CXXDirectInit) { assert(DirectInit && "Call-style initializer must be direct init."); VDecl->setInitStyle(VarDecl::CallInit); } else if (DirectInit) { // This must be list-initialization. No other way is direct-initialization. VDecl->setInitStyle(VarDecl::ListInit); } CheckCompleteVariableDeclaration(VDecl); } /// ActOnInitializerError - Given that there was an error parsing an /// initializer for the given declaration, try to return to some form /// of sanity. void Sema::ActOnInitializerError(Decl *D) { // Our main concern here is re-establishing invariants like "a // variable's type is either dependent or complete". if (!D || D->isInvalidDecl()) return; VarDecl *VD = dyn_cast(D); if (!VD) return; // Bindings are not usable if we can't make sense of the initializer. if (auto *DD = dyn_cast(D)) for (auto *BD : DD->bindings()) BD->setInvalidDecl(); // Auto types are meaningless if we can't make sense of the initializer. if (ParsingInitForAutoVars.count(D)) { D->setInvalidDecl(); return; } QualType Ty = VD->getType(); if (Ty->isDependentType()) return; // Require a complete type. if (RequireCompleteType(VD->getLocation(), Context.getBaseElementType(Ty), diag::err_typecheck_decl_incomplete_type)) { VD->setInvalidDecl(); return; } // Require a non-abstract type. if (RequireNonAbstractType(VD->getLocation(), Ty, diag::err_abstract_type_in_decl, AbstractVariableType)) { VD->setInvalidDecl(); return; } // Don't bother complaining about constructors or destructors, // though. } void Sema::ActOnUninitializedDecl(Decl *RealDecl) { // If there is no declaration, there was an error parsing it. Just ignore it. if (!RealDecl) return; if (VarDecl *Var = dyn_cast(RealDecl)) { QualType Type = Var->getType(); // C++1z [dcl.dcl]p1 grammar implies that an initializer is mandatory. if (isa(RealDecl)) { Diag(Var->getLocation(), diag::err_decomp_decl_requires_init) << Var; Var->setInvalidDecl(); return; } if (Type->isUndeducedType() && DeduceVariableDeclarationType(Var, false, nullptr)) return; // C++11 [class.static.data]p3: A static data member can be declared with // the constexpr specifier; if so, its declaration shall specify // a brace-or-equal-initializer. // C++11 [dcl.constexpr]p1: The constexpr specifier shall be applied only to // the definition of a variable [...] or the declaration of a static data // member. if (Var->isConstexpr() && !Var->isThisDeclarationADefinition() && !Var->isThisDeclarationADemotedDefinition()) { if (Var->isStaticDataMember()) { // C++1z removes the relevant rule; the in-class declaration is always // a definition there. if (!getLangOpts().CPlusPlus1z) { Diag(Var->getLocation(), diag::err_constexpr_static_mem_var_requires_init) << Var->getDeclName(); Var->setInvalidDecl(); return; } } else { Diag(Var->getLocation(), diag::err_invalid_constexpr_var_decl); Var->setInvalidDecl(); return; } } // C++ Concepts TS [dcl.spec.concept]p1: [...] A variable template // definition having the concept specifier is called a variable concept. A // concept definition refers to [...] a variable concept and its initializer. if (VarTemplateDecl *VTD = Var->getDescribedVarTemplate()) { if (VTD->isConcept()) { Diag(Var->getLocation(), diag::err_var_concept_not_initialized); Var->setInvalidDecl(); return; } } // OpenCL v1.1 s6.5.3: variables declared in the constant address space must // be initialized. if (!Var->isInvalidDecl() && Var->getType().getAddressSpace() == LangAS::opencl_constant && Var->getStorageClass() != SC_Extern && !Var->getInit()) { Diag(Var->getLocation(), diag::err_opencl_constant_no_init); Var->setInvalidDecl(); return; } switch (Var->isThisDeclarationADefinition()) { case VarDecl::Definition: if (!Var->isStaticDataMember() || !Var->getAnyInitializer()) break; // We have an out-of-line definition of a static data member // that has an in-class initializer, so we type-check this like // a declaration. // // Fall through case VarDecl::DeclarationOnly: // It's only a declaration. // Block scope. C99 6.7p7: If an identifier for an object is // declared with no linkage (C99 6.2.2p6), the type for the // object shall be complete. if (!Type->isDependentType() && Var->isLocalVarDecl() && !Var->hasLinkage() && !Var->isInvalidDecl() && RequireCompleteType(Var->getLocation(), Type, diag::err_typecheck_decl_incomplete_type)) Var->setInvalidDecl(); // Make sure that the type is not abstract. if (!Type->isDependentType() && !Var->isInvalidDecl() && RequireNonAbstractType(Var->getLocation(), Type, diag::err_abstract_type_in_decl, AbstractVariableType)) Var->setInvalidDecl(); if (!Type->isDependentType() && !Var->isInvalidDecl() && Var->getStorageClass() == SC_PrivateExtern) { Diag(Var->getLocation(), diag::warn_private_extern); Diag(Var->getLocation(), diag::note_private_extern); } return; case VarDecl::TentativeDefinition: // File scope. C99 6.9.2p2: A declaration of an identifier for an // object that has file scope without an initializer, and without a // storage-class specifier or with the storage-class specifier "static", // constitutes a tentative definition. Note: A tentative definition with // external linkage is valid (C99 6.2.2p5). if (!Var->isInvalidDecl()) { if (const IncompleteArrayType *ArrayT = Context.getAsIncompleteArrayType(Type)) { if (RequireCompleteType(Var->getLocation(), ArrayT->getElementType(), diag::err_illegal_decl_array_incomplete_type)) Var->setInvalidDecl(); } else if (Var->getStorageClass() == SC_Static) { // C99 6.9.2p3: If the declaration of an identifier for an object is // a tentative definition and has internal linkage (C99 6.2.2p3), the // declared type shall not be an incomplete type. // NOTE: code such as the following // static struct s; // struct s { int a; }; // is accepted by gcc. Hence here we issue a warning instead of // an error and we do not invalidate the static declaration. // NOTE: to avoid multiple warnings, only check the first declaration. if (Var->isFirstDecl()) RequireCompleteType(Var->getLocation(), Type, diag::ext_typecheck_decl_incomplete_type); } } // Record the tentative definition; we're done. if (!Var->isInvalidDecl()) TentativeDefinitions.push_back(Var); return; } // Provide a specific diagnostic for uninitialized variable // definitions with incomplete array type. if (Type->isIncompleteArrayType()) { Diag(Var->getLocation(), diag::err_typecheck_incomplete_array_needs_initializer); Var->setInvalidDecl(); return; } // Provide a specific diagnostic for uninitialized variable // definitions with reference type. if (Type->isReferenceType()) { Diag(Var->getLocation(), diag::err_reference_var_requires_init) << Var->getDeclName() << SourceRange(Var->getLocation(), Var->getLocation()); Var->setInvalidDecl(); return; } // Do not attempt to type-check the default initializer for a // variable with dependent type. if (Type->isDependentType()) return; if (Var->isInvalidDecl()) return; if (!Var->hasAttr()) { if (RequireCompleteType(Var->getLocation(), Context.getBaseElementType(Type), diag::err_typecheck_decl_incomplete_type)) { Var->setInvalidDecl(); return; } } else { return; } // The variable can not have an abstract class type. if (RequireNonAbstractType(Var->getLocation(), Type, diag::err_abstract_type_in_decl, AbstractVariableType)) { Var->setInvalidDecl(); return; } // Check for jumps past the implicit initializer. C++0x // clarifies that this applies to a "variable with automatic // storage duration", not a "local variable". // C++11 [stmt.dcl]p3 // A program that jumps from a point where a variable with automatic // storage duration is not in scope to a point where it is in scope is // ill-formed unless the variable has scalar type, class type with a // trivial default constructor and a trivial destructor, a cv-qualified // version of one of these types, or an array of one of the preceding // types and is declared without an initializer. if (getLangOpts().CPlusPlus && Var->hasLocalStorage()) { if (const RecordType *Record = Context.getBaseElementType(Type)->getAs()) { CXXRecordDecl *CXXRecord = cast(Record->getDecl()); // Mark the function for further checking even if the looser rules of // C++11 do not require such checks, so that we can diagnose // incompatibilities with C++98. if (!CXXRecord->isPOD()) getCurFunction()->setHasBranchProtectedScope(); } } // C++03 [dcl.init]p9: // If no initializer is specified for an object, and the // object is of (possibly cv-qualified) non-POD class type (or // array thereof), the object shall be default-initialized; if // the object is of const-qualified type, the underlying class // type shall have a user-declared default // constructor. Otherwise, if no initializer is specified for // a non- static object, the object and its subobjects, if // any, have an indeterminate initial value); if the object // or any of its subobjects are of const-qualified type, the // program is ill-formed. // C++0x [dcl.init]p11: // If no initializer is specified for an object, the object is // default-initialized; [...]. InitializedEntity Entity = InitializedEntity::InitializeVariable(Var); InitializationKind Kind = InitializationKind::CreateDefault(Var->getLocation()); InitializationSequence InitSeq(*this, Entity, Kind, None); ExprResult Init = InitSeq.Perform(*this, Entity, Kind, None); if (Init.isInvalid()) Var->setInvalidDecl(); else if (Init.get()) { Var->setInit(MaybeCreateExprWithCleanups(Init.get())); // This is important for template substitution. Var->setInitStyle(VarDecl::CallInit); } CheckCompleteVariableDeclaration(Var); } } void Sema::ActOnCXXForRangeDecl(Decl *D) { // If there is no declaration, there was an error parsing it. Ignore it. if (!D) return; VarDecl *VD = dyn_cast(D); if (!VD) { Diag(D->getLocation(), diag::err_for_range_decl_must_be_var); D->setInvalidDecl(); return; } VD->setCXXForRangeDecl(true); // for-range-declaration cannot be given a storage class specifier. int Error = -1; switch (VD->getStorageClass()) { case SC_None: break; case SC_Extern: Error = 0; break; case SC_Static: Error = 1; break; case SC_PrivateExtern: Error = 2; break; case SC_Auto: Error = 3; break; case SC_Register: Error = 4; break; } if (Error != -1) { Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class) << VD->getDeclName() << Error; D->setInvalidDecl(); } } StmtResult Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, IdentifierInfo *Ident, ParsedAttributes &Attrs, SourceLocation AttrEnd) { // C++1y [stmt.iter]p1: // A range-based for statement of the form // for ( for-range-identifier : for-range-initializer ) statement // is equivalent to // for ( auto&& for-range-identifier : for-range-initializer ) statement DeclSpec DS(Attrs.getPool().getFactory()); const char *PrevSpec; unsigned DiagID; DS.SetTypeSpecType(DeclSpec::TST_auto, IdentLoc, PrevSpec, DiagID, getPrintingPolicy()); Declarator D(DS, Declarator::ForContext); D.SetIdentifier(Ident, IdentLoc); D.takeAttributes(Attrs, AttrEnd); ParsedAttributes EmptyAttrs(Attrs.getPool().getFactory()); D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/false), EmptyAttrs, IdentLoc); Decl *Var = ActOnDeclarator(S, D); cast(Var)->setCXXForRangeDecl(true); FinalizeDeclaration(Var); return ActOnDeclStmt(FinalizeDeclaratorGroup(S, DS, Var), IdentLoc, AttrEnd.isValid() ? AttrEnd : IdentLoc); } void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { if (var->isInvalidDecl()) return; if (getLangOpts().OpenCL) { // OpenCL v2.0 s6.12.5 - Every block variable declaration must have an // initialiser if (var->getTypeSourceInfo()->getType()->isBlockPointerType() && !var->hasInit()) { Diag(var->getLocation(), diag::err_opencl_invalid_block_declaration) << 1 /*Init*/; var->setInvalidDecl(); return; } } // In Objective-C, don't allow jumps past the implicit initialization of a // local retaining variable. if (getLangOpts().ObjC1 && var->hasLocalStorage()) { switch (var->getType().getObjCLifetime()) { case Qualifiers::OCL_None: case Qualifiers::OCL_ExplicitNone: case Qualifiers::OCL_Autoreleasing: break; case Qualifiers::OCL_Weak: case Qualifiers::OCL_Strong: getCurFunction()->setHasBranchProtectedScope(); break; } } // Warn about externally-visible variables being defined without a // prior declaration. We only want to do this for global // declarations, but we also specifically need to avoid doing it for // class members because the linkage of an anonymous class can // change if it's later given a typedef name. if (var->isThisDeclarationADefinition() && var->getDeclContext()->getRedeclContext()->isFileContext() && var->isExternallyVisible() && var->hasLinkage() && !getDiagnostics().isIgnored(diag::warn_missing_variable_declarations, var->getLocation())) { // Find a previous declaration that's not a definition. VarDecl *prev = var->getPreviousDecl(); while (prev && prev->isThisDeclarationADefinition()) prev = prev->getPreviousDecl(); if (!prev) Diag(var->getLocation(), diag::warn_missing_variable_declarations) << var; } // Cache the result of checking for constant initialization. Optional CacheHasConstInit; const Expr *CacheCulprit; auto checkConstInit = [&]() mutable { if (!CacheHasConstInit) CacheHasConstInit = var->getInit()->isConstantInitializer( Context, var->getType()->isReferenceType(), &CacheCulprit); return *CacheHasConstInit; }; if (var->getTLSKind() == VarDecl::TLS_Static) { if (var->getType().isDestructedType()) { // GNU C++98 edits for __thread, [basic.start.term]p3: // The type of an object with thread storage duration shall not // have a non-trivial destructor. Diag(var->getLocation(), diag::err_thread_nontrivial_dtor); if (getLangOpts().CPlusPlus11) Diag(var->getLocation(), diag::note_use_thread_local); } else if (getLangOpts().CPlusPlus && var->hasInit()) { if (!checkConstInit()) { // GNU C++98 edits for __thread, [basic.start.init]p4: // An object of thread storage duration shall not require dynamic // initialization. // FIXME: Need strict checking here. Diag(CacheCulprit->getExprLoc(), diag::err_thread_dynamic_init) << CacheCulprit->getSourceRange(); if (getLangOpts().CPlusPlus11) Diag(var->getLocation(), diag::note_use_thread_local); } } } // Apply section attributes and pragmas to global variables. bool GlobalStorage = var->hasGlobalStorage(); if (GlobalStorage && var->isThisDeclarationADefinition() && !inTemplateInstantiation()) { PragmaStack *Stack = nullptr; int SectionFlags = ASTContext::PSF_Implicit | ASTContext::PSF_Read; if (var->getType().isConstQualified()) Stack = &ConstSegStack; else if (!var->getInit()) { Stack = &BSSSegStack; SectionFlags |= ASTContext::PSF_Write; } else { Stack = &DataSegStack; SectionFlags |= ASTContext::PSF_Write; } if (Stack->CurrentValue && !var->hasAttr()) { var->addAttr(SectionAttr::CreateImplicit( Context, SectionAttr::Declspec_allocate, Stack->CurrentValue->getString(), Stack->CurrentPragmaLocation)); } if (const SectionAttr *SA = var->getAttr()) if (UnifySection(SA->getName(), SectionFlags, var)) var->dropAttr(); // Apply the init_seg attribute if this has an initializer. If the // initializer turns out to not be dynamic, we'll end up ignoring this // attribute. if (CurInitSeg && var->getInit()) var->addAttr(InitSegAttr::CreateImplicit(Context, CurInitSeg->getString(), CurInitSegLoc)); } // All the following checks are C++ only. if (!getLangOpts().CPlusPlus) { // If this variable must be emitted, add it as an initializer for the // current module. if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty()) Context.addModuleInitializer(ModuleScopes.back().Module, var); return; } if (auto *DD = dyn_cast(var)) CheckCompleteDecompositionDeclaration(DD); QualType type = var->getType(); if (type->isDependentType()) return; // __block variables might require us to capture a copy-initializer. if (var->hasAttr()) { // It's currently invalid to ever have a __block variable with an // array type; should we diagnose that here? // Regardless, we don't want to ignore array nesting when // constructing this copy. if (type->isStructureOrClassType()) { EnterExpressionEvaluationContext scope( *this, ExpressionEvaluationContext::PotentiallyEvaluated); SourceLocation poi = var->getLocation(); Expr *varRef =new (Context) DeclRefExpr(var, false, type, VK_LValue, poi); ExprResult result = PerformMoveOrCopyInitialization( InitializedEntity::InitializeBlock(poi, type, false), var, var->getType(), varRef, /*AllowNRVO=*/true); if (!result.isInvalid()) { result = MaybeCreateExprWithCleanups(result); Expr *init = result.getAs(); Context.setBlockVarCopyInits(var, init); } } } Expr *Init = var->getInit(); bool IsGlobal = GlobalStorage && !var->isStaticLocal(); QualType baseType = Context.getBaseElementType(type); if (Init && !Init->isValueDependent()) { if (var->isConstexpr()) { SmallVector Notes; if (!var->evaluateValue(Notes) || !var->isInitICE()) { SourceLocation DiagLoc = var->getLocation(); // If the note doesn't add any useful information other than a source // location, fold it into the primary diagnostic. if (Notes.size() == 1 && Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr) { DiagLoc = Notes[0].first; Notes.clear(); } Diag(DiagLoc, diag::err_constexpr_var_requires_const_init) << var << Init->getSourceRange(); for (unsigned I = 0, N = Notes.size(); I != N; ++I) Diag(Notes[I].first, Notes[I].second); } } else if (var->isUsableInConstantExpressions(Context)) { // Check whether the initializer of a const variable of integral or // enumeration type is an ICE now, since we can't tell whether it was // initialized by a constant expression if we check later. var->checkInitIsICE(); } // Don't emit further diagnostics about constexpr globals since they // were just diagnosed. if (!var->isConstexpr() && GlobalStorage && var->hasAttr()) { // FIXME: Need strict checking in C++03 here. bool DiagErr = getLangOpts().CPlusPlus11 ? !var->checkInitIsICE() : !checkConstInit(); if (DiagErr) { auto attr = var->getAttr(); Diag(var->getLocation(), diag::err_require_constant_init_failed) << Init->getSourceRange(); Diag(attr->getLocation(), diag::note_declared_required_constant_init_here) << attr->getRange(); if (getLangOpts().CPlusPlus11) { APValue Value; SmallVector Notes; Init->EvaluateAsInitializer(Value, getASTContext(), var, Notes); for (auto &it : Notes) Diag(it.first, it.second); } else { Diag(CacheCulprit->getExprLoc(), diag::note_invalid_subexpr_in_const_expr) << CacheCulprit->getSourceRange(); } } } else if (!var->isConstexpr() && IsGlobal && !getDiagnostics().isIgnored(diag::warn_global_constructor, var->getLocation())) { // Warn about globals which don't have a constant initializer. Don't // warn about globals with a non-trivial destructor because we already // warned about them. CXXRecordDecl *RD = baseType->getAsCXXRecordDecl(); if (!(RD && !RD->hasTrivialDestructor())) { if (!checkConstInit()) Diag(var->getLocation(), diag::warn_global_constructor) << Init->getSourceRange(); } } } // Require the destructor. if (const RecordType *recordType = baseType->getAs()) FinalizeVarWithDestructor(var, recordType); // If this variable must be emitted, add it as an initializer for the current // module. if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty()) Context.addModuleInitializer(ModuleScopes.back().Module, var); } /// \brief Determines if a variable's alignment is dependent. static bool hasDependentAlignment(VarDecl *VD) { if (VD->getType()->isDependentType()) return true; for (auto *I : VD->specific_attrs()) if (I->isAlignmentDependent()) return true; return false; } /// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform /// any semantic actions necessary after any initializer has been attached. void Sema::FinalizeDeclaration(Decl *ThisDecl) { // Note that we are no longer parsing the initializer for this declaration. ParsingInitForAutoVars.erase(ThisDecl); VarDecl *VD = dyn_cast_or_null(ThisDecl); if (!VD) return; // Apply an implicit SectionAttr if '#pragma clang section bss|data|rodata' is active if (VD->hasGlobalStorage() && VD->isThisDeclarationADefinition() && !inTemplateInstantiation() && !VD->hasAttr()) { if (PragmaClangBSSSection.Valid) VD->addAttr(PragmaClangBSSSectionAttr::CreateImplicit(Context, PragmaClangBSSSection.SectionName, PragmaClangBSSSection.PragmaLocation)); if (PragmaClangDataSection.Valid) VD->addAttr(PragmaClangDataSectionAttr::CreateImplicit(Context, PragmaClangDataSection.SectionName, PragmaClangDataSection.PragmaLocation)); if (PragmaClangRodataSection.Valid) VD->addAttr(PragmaClangRodataSectionAttr::CreateImplicit(Context, PragmaClangRodataSection.SectionName, PragmaClangRodataSection.PragmaLocation)); } if (auto *DD = dyn_cast(ThisDecl)) { for (auto *BD : DD->bindings()) { FinalizeDeclaration(BD); } } checkAttributesAfterMerging(*this, *VD); // Perform TLS alignment check here after attributes attached to the variable // which may affect the alignment have been processed. Only perform the check // if the target has a maximum TLS alignment (zero means no constraints). if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) { // Protect the check so that it's not performed on dependent types and // dependent alignments (we can't determine the alignment in that case). if (VD->getTLSKind() && !hasDependentAlignment(VD) && !VD->isInvalidDecl()) { CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign); if (Context.getDeclAlign(VD) > MaxAlignChars) { Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum) << (unsigned)Context.getDeclAlign(VD).getQuantity() << VD << (unsigned)MaxAlignChars.getQuantity(); } } } if (VD->isStaticLocal()) { if (FunctionDecl *FD = dyn_cast_or_null(VD->getParentFunctionOrMethod())) { // Static locals inherit dll attributes from their function. if (Attr *A = getDLLAttr(FD)) { auto *NewAttr = cast(A->clone(getASTContext())); NewAttr->setInherited(true); VD->addAttr(NewAttr); } // CUDA E.2.9.4: Within the body of a __device__ or __global__ // function, only __shared__ variables may be declared with // static storage class. if (getLangOpts().CUDA && !VD->hasAttr() && CUDADiagIfDeviceCode(VD->getLocation(), diag::err_device_static_local_var) << CurrentCUDATarget()) VD->setInvalidDecl(); } } // Perform check for initializers of device-side global variables. // CUDA allows empty constructors as initializers (see E.2.3.1, CUDA // 7.5). We must also apply the same checks to all __shared__ // variables whether they are local or not. CUDA also allows // constant initializers for __constant__ and __device__ variables. if (getLangOpts().CUDA) { const Expr *Init = VD->getInit(); if (Init && VD->hasGlobalStorage()) { if (VD->hasAttr() || VD->hasAttr() || VD->hasAttr()) { assert(!VD->isStaticLocal() || VD->hasAttr()); bool AllowedInit = false; if (const CXXConstructExpr *CE = dyn_cast(Init)) AllowedInit = isEmptyCudaConstructor(VD->getLocation(), CE->getConstructor()); // We'll allow constant initializers even if it's a non-empty // constructor according to CUDA rules. This deviates from NVCC, // but allows us to handle things like constexpr constructors. if (!AllowedInit && (VD->hasAttr() || VD->hasAttr())) AllowedInit = VD->getInit()->isConstantInitializer( Context, VD->getType()->isReferenceType()); // Also make sure that destructor, if there is one, is empty. if (AllowedInit) if (CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl()) AllowedInit = isEmptyCudaDestructor(VD->getLocation(), RD->getDestructor()); if (!AllowedInit) { Diag(VD->getLocation(), VD->hasAttr() ? diag::err_shared_var_init : diag::err_dynamic_var_init) << Init->getSourceRange(); VD->setInvalidDecl(); } } else { // This is a host-side global variable. Check that the initializer is // callable from the host side. const FunctionDecl *InitFn = nullptr; if (const CXXConstructExpr *CE = dyn_cast(Init)) { InitFn = CE->getConstructor(); } else if (const CallExpr *CE = dyn_cast(Init)) { InitFn = CE->getDirectCallee(); } if (InitFn) { CUDAFunctionTarget InitFnTarget = IdentifyCUDATarget(InitFn); if (InitFnTarget != CFT_Host && InitFnTarget != CFT_HostDevice) { Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer) << InitFnTarget << InitFn; Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn; VD->setInvalidDecl(); } } } } } // Grab the dllimport or dllexport attribute off of the VarDecl. const InheritableAttr *DLLAttr = getDLLAttr(VD); // Imported static data members cannot be defined out-of-line. if (const auto *IA = dyn_cast_or_null(DLLAttr)) { if (VD->isStaticDataMember() && VD->isOutOfLine() && VD->isThisDeclarationADefinition()) { // We allow definitions of dllimport class template static data members // with a warning. CXXRecordDecl *Context = cast(VD->getFirstDecl()->getDeclContext()); bool IsClassTemplateMember = isa(Context) || Context->getDescribedClassTemplate(); Diag(VD->getLocation(), IsClassTemplateMember ? diag::warn_attribute_dllimport_static_field_definition : diag::err_attribute_dllimport_static_field_definition); Diag(IA->getLocation(), diag::note_attribute); if (!IsClassTemplateMember) VD->setInvalidDecl(); } } // dllimport/dllexport variables cannot be thread local, their TLS index // isn't exported with the variable. if (DLLAttr && VD->getTLSKind()) { auto *F = dyn_cast_or_null(VD->getParentFunctionOrMethod()); if (F && getDLLAttr(F)) { assert(VD->isStaticLocal()); // But if this is a static local in a dlimport/dllexport function, the // function will never be inlined, which means the var would never be // imported, so having it marked import/export is safe. } else { Diag(VD->getLocation(), diag::err_attribute_dll_thread_local) << VD << DLLAttr; VD->setInvalidDecl(); } } if (UsedAttr *Attr = VD->getAttr()) { if (!Attr->isInherited() && !VD->isThisDeclarationADefinition()) { Diag(Attr->getLocation(), diag::warn_attribute_ignored) << Attr; VD->dropAttr(); } } const DeclContext *DC = VD->getDeclContext(); // If there's a #pragma GCC visibility in scope, and this isn't a class // member, set the visibility of this variable. if (DC->getRedeclContext()->isFileContext() && VD->isExternallyVisible()) AddPushedVisibilityAttribute(VD); // FIXME: Warn on unused var template partial specializations. if (VD->isFileVarDecl() && !isa(VD)) MarkUnusedFileScopedDecl(VD); // Now we have parsed the initializer and can update the table of magic // tag values. if (!VD->hasAttr() || !VD->getType()->isIntegralOrEnumerationType()) return; for (const auto *I : ThisDecl->specific_attrs()) { const Expr *MagicValueExpr = VD->getInit(); if (!MagicValueExpr) { continue; } llvm::APSInt MagicValueInt; if (!MagicValueExpr->isIntegerConstantExpr(MagicValueInt, Context)) { Diag(I->getRange().getBegin(), diag::err_type_tag_for_datatype_not_ice) << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange(); continue; } if (MagicValueInt.getActiveBits() > 64) { Diag(I->getRange().getBegin(), diag::err_type_tag_for_datatype_too_large) << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange(); continue; } uint64_t MagicValue = MagicValueInt.getZExtValue(); RegisterTypeTagForDatatype(I->getArgumentKind(), MagicValue, I->getMatchingCType(), I->getLayoutCompatible(), I->getMustBeNull()); } } static bool hasDeducedAuto(DeclaratorDecl *DD) { auto *VD = dyn_cast(DD); return VD && !VD->getType()->hasAutoForTrailingReturnType(); } Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, ArrayRef Group) { SmallVector Decls; if (DS.isTypeSpecOwned()) Decls.push_back(DS.getRepAsDecl()); DeclaratorDecl *FirstDeclaratorInGroup = nullptr; DecompositionDecl *FirstDecompDeclaratorInGroup = nullptr; bool DiagnosedMultipleDecomps = false; DeclaratorDecl *FirstNonDeducedAutoInGroup = nullptr; bool DiagnosedNonDeducedAuto = false; for (unsigned i = 0, e = Group.size(); i != e; ++i) { if (Decl *D = Group[i]) { // For declarators, there are some additional syntactic-ish checks we need // to perform. if (auto *DD = dyn_cast(D)) { if (!FirstDeclaratorInGroup) FirstDeclaratorInGroup = DD; if (!FirstDecompDeclaratorInGroup) FirstDecompDeclaratorInGroup = dyn_cast(D); if (!FirstNonDeducedAutoInGroup && DS.hasAutoTypeSpec() && !hasDeducedAuto(DD)) FirstNonDeducedAutoInGroup = DD; if (FirstDeclaratorInGroup != DD) { // A decomposition declaration cannot be combined with any other // declaration in the same group. if (FirstDecompDeclaratorInGroup && !DiagnosedMultipleDecomps) { Diag(FirstDecompDeclaratorInGroup->getLocation(), diag::err_decomp_decl_not_alone) << FirstDeclaratorInGroup->getSourceRange() << DD->getSourceRange(); DiagnosedMultipleDecomps = true; } // A declarator that uses 'auto' in any way other than to declare a // variable with a deduced type cannot be combined with any other // declarator in the same group. if (FirstNonDeducedAutoInGroup && !DiagnosedNonDeducedAuto) { Diag(FirstNonDeducedAutoInGroup->getLocation(), diag::err_auto_non_deduced_not_alone) << FirstNonDeducedAutoInGroup->getType() ->hasAutoForTrailingReturnType() << FirstDeclaratorInGroup->getSourceRange() << DD->getSourceRange(); DiagnosedNonDeducedAuto = true; } } } Decls.push_back(D); } } if (DeclSpec::isDeclRep(DS.getTypeSpecType())) { if (TagDecl *Tag = dyn_cast_or_null(DS.getRepAsDecl())) { handleTagNumbering(Tag, S); if (FirstDeclaratorInGroup && !Tag->hasNameForLinkage() && getLangOpts().CPlusPlus) Context.addDeclaratorForUnnamedTagDecl(Tag, FirstDeclaratorInGroup); } } return BuildDeclaratorGroup(Decls); } /// BuildDeclaratorGroup - convert a list of declarations into a declaration /// group, performing any necessary semantic checking. Sema::DeclGroupPtrTy Sema::BuildDeclaratorGroup(MutableArrayRef Group) { // C++14 [dcl.spec.auto]p7: (DR1347) // If the type that replaces the placeholder type is not the same in each // deduction, the program is ill-formed. if (Group.size() > 1) { QualType Deduced; VarDecl *DeducedDecl = nullptr; for (unsigned i = 0, e = Group.size(); i != e; ++i) { VarDecl *D = dyn_cast(Group[i]); if (!D || D->isInvalidDecl()) break; DeducedType *DT = D->getType()->getContainedDeducedType(); if (!DT || DT->getDeducedType().isNull()) continue; if (Deduced.isNull()) { Deduced = DT->getDeducedType(); DeducedDecl = D; } else if (!Context.hasSameType(DT->getDeducedType(), Deduced)) { auto *AT = dyn_cast(DT); Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(), diag::err_auto_different_deductions) << (AT ? (unsigned)AT->getKeyword() : 3) << Deduced << DeducedDecl->getDeclName() << DT->getDeducedType() << D->getDeclName() << DeducedDecl->getInit()->getSourceRange() << D->getInit()->getSourceRange(); D->setInvalidDecl(); break; } } } ActOnDocumentableDecls(Group); return DeclGroupPtrTy::make( DeclGroupRef::Create(Context, Group.data(), Group.size())); } void Sema::ActOnDocumentableDecl(Decl *D) { ActOnDocumentableDecls(D); } void Sema::ActOnDocumentableDecls(ArrayRef Group) { // Don't parse the comment if Doxygen diagnostics are ignored. if (Group.empty() || !Group[0]) return; if (Diags.isIgnored(diag::warn_doc_param_not_found, Group[0]->getLocation()) && Diags.isIgnored(diag::warn_unknown_comment_command_name, Group[0]->getLocation())) return; if (Group.size() >= 2) { // This is a decl group. Normally it will contain only declarations // produced from declarator list. But in case we have any definitions or // additional declaration references: // 'typedef struct S {} S;' // 'typedef struct S *S;' // 'struct S *pS;' // FinalizeDeclaratorGroup adds these as separate declarations. Decl *MaybeTagDecl = Group[0]; if (MaybeTagDecl && isa(MaybeTagDecl)) { Group = Group.slice(1); } } // See if there are any new comments that are not attached to a decl. ArrayRef Comments = Context.getRawCommentList().getComments(); if (!Comments.empty() && !Comments.back()->isAttached()) { // There is at least one comment that not attached to a decl. // Maybe it should be attached to one of these decls? // // Note that this way we pick up not only comments that precede the // declaration, but also comments that *follow* the declaration -- thanks to // the lookahead in the lexer: we've consumed the semicolon and looked // ahead through comments. for (unsigned i = 0, e = Group.size(); i != e; ++i) Context.getCommentForDecl(Group[i], &PP); } } /// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator() /// to introduce parameters into function prototype scope. Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { const DeclSpec &DS = D.getDeclSpec(); // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. // C++03 [dcl.stc]p2 also permits 'auto'. StorageClass SC = SC_None; if (DS.getStorageClassSpec() == DeclSpec::SCS_register) { SC = SC_Register; } else if (getLangOpts().CPlusPlus && DS.getStorageClassSpec() == DeclSpec::SCS_auto) { SC = SC_Auto; } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) { Diag(DS.getStorageClassSpecLoc(), diag::err_invalid_storage_class_in_func_decl); D.getMutableDeclSpec().ClearStorageClassSpecs(); } if (DeclSpec::TSCS TSCS = DS.getThreadStorageClassSpec()) Diag(DS.getThreadStorageClassSpecLoc(), diag::err_invalid_thread) << DeclSpec::getSpecifierName(TSCS); if (DS.isInlineSpecified()) Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function) << getLangOpts().CPlusPlus1z; if (DS.isConstexprSpecified()) Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr) << 0; if (DS.isConceptSpecified()) Diag(DS.getConceptSpecLoc(), diag::err_concept_wrong_decl_kind); DiagnoseFunctionSpecifiers(DS); TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType parmDeclType = TInfo->getType(); if (getLangOpts().CPlusPlus) { // Check that there are no default arguments inside the type of this // parameter. CheckExtraCXXDefaultArguments(D); // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1). if (D.getCXXScopeSpec().isSet()) { Diag(D.getIdentifierLoc(), diag::err_qualified_param_declarator) << D.getCXXScopeSpec().getRange(); D.getCXXScopeSpec().clear(); } } // Ensure we have a valid name IdentifierInfo *II = nullptr; if (D.hasName()) { II = D.getIdentifier(); if (!II) { Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name) << GetNameForDeclarator(D).getName(); D.setInvalidType(true); } } // Check for redeclaration of parameters, e.g. int foo(int x, int x); if (II) { LookupResult R(*this, II, D.getIdentifierLoc(), LookupOrdinaryName, ForRedeclaration); LookupName(R, S); if (R.isSingleResult()) { NamedDecl *PrevDecl = R.getFoundDecl(); if (PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); // Just pretend that we didn't see the previous declaration. PrevDecl = nullptr; } else if (S->isDeclScope(PrevDecl)) { Diag(D.getIdentifierLoc(), diag::err_param_redefinition) << II; Diag(PrevDecl->getLocation(), diag::note_previous_declaration); // Recover by removing the name II = nullptr; D.SetIdentifier(nullptr, D.getIdentifierLoc()); D.setInvalidType(true); } } } // Temporarily put parameter variables in the translation unit, not // the enclosing context. This prevents them from accidentally // looking like class members in C++. ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(), D.getLocStart(), D.getIdentifierLoc(), II, parmDeclType, TInfo, SC); if (D.isInvalidType()) New->setInvalidDecl(); assert(S->isFunctionPrototypeScope()); assert(S->getFunctionPrototypeDepth() >= 1); New->setScopeInfo(S->getFunctionPrototypeDepth() - 1, S->getNextFunctionPrototypeIndex()); // Add the parameter declaration into this scope. S->AddDecl(New); if (II) IdResolver.AddDecl(New); ProcessDeclAttributes(S, New, D); if (D.getDeclSpec().isModulePrivateSpecified()) Diag(New->getLocation(), diag::err_module_private_local) << 1 << New->getDeclName() << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); if (New->hasAttr()) { Diag(New->getLocation(), diag::err_block_on_nonlocal); } return New; } /// \brief Synthesizes a variable for a parameter arising from a /// typedef. ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, QualType T) { /* FIXME: setting StartLoc == Loc. Would it be worth to modify callers so as to provide proper source location for the unnamed parameters, embedding the parameter's type? */ ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, nullptr, T, Context.getTrivialTypeSourceInfo(T, Loc), SC_None, nullptr); Param->setImplicit(); return Param; } void Sema::DiagnoseUnusedParameters(ArrayRef Parameters) { // Don't diagnose unused-parameter errors in template instantiations; we // will already have done so in the template itself. if (inTemplateInstantiation()) return; for (const ParmVarDecl *Parameter : Parameters) { if (!Parameter->isReferenced() && Parameter->getDeclName() && !Parameter->hasAttr()) { Diag(Parameter->getLocation(), diag::warn_unused_parameter) << Parameter->getDeclName(); } } } void Sema::DiagnoseSizeOfParametersAndReturnValue( ArrayRef Parameters, QualType ReturnTy, NamedDecl *D) { if (LangOpts.NumLargeByValueCopy == 0) // No check. return; // Warn if the return value is pass-by-value and larger than the specified // threshold. if (!ReturnTy->isDependentType() && ReturnTy.isPODType(Context)) { unsigned Size = Context.getTypeSizeInChars(ReturnTy).getQuantity(); if (Size > LangOpts.NumLargeByValueCopy) Diag(D->getLocation(), diag::warn_return_value_size) << D->getDeclName() << Size; } // Warn if any parameter is pass-by-value and larger than the specified // threshold. for (const ParmVarDecl *Parameter : Parameters) { QualType T = Parameter->getType(); if (T->isDependentType() || !T.isPODType(Context)) continue; unsigned Size = Context.getTypeSizeInChars(T).getQuantity(); if (Size > LangOpts.NumLargeByValueCopy) Diag(Parameter->getLocation(), diag::warn_parameter_size) << Parameter->getDeclName() << Size; } } ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, SourceLocation NameLoc, IdentifierInfo *Name, QualType T, TypeSourceInfo *TSInfo, StorageClass SC) { // In ARC, infer a lifetime qualifier for appropriate parameter types. if (getLangOpts().ObjCAutoRefCount && T.getObjCLifetime() == Qualifiers::OCL_None && T->isObjCLifetimeType()) { Qualifiers::ObjCLifetime lifetime; // Special cases for arrays: // - if it's const, use __unsafe_unretained // - otherwise, it's an error if (T->isArrayType()) { if (!T.isConstQualified()) { DelayedDiagnostics.add( sema::DelayedDiagnostic::makeForbiddenType( NameLoc, diag::err_arc_array_param_no_ownership, T, false)); } lifetime = Qualifiers::OCL_ExplicitNone; } else { lifetime = T->getObjCARCImplicitLifetime(); } T = Context.getLifetimeQualifiedType(T, lifetime); } ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name, Context.getAdjustedParameterType(T), TSInfo, SC, nullptr); // Parameters can not be abstract class types. // For record types, this is done by the AbstractClassUsageDiagnoser once // the class has been completely parsed. if (!CurContext->isRecord() && RequireNonAbstractType(NameLoc, T, diag::err_abstract_type_in_decl, AbstractParamType)) New->setInvalidDecl(); // Parameter declarators cannot be interface types. All ObjC objects are // passed by reference. if (T->isObjCObjectType()) { SourceLocation TypeEndLoc = getLocForEndOfToken(TSInfo->getTypeLoc().getLocEnd()); Diag(NameLoc, diag::err_object_cannot_be_passed_returned_by_value) << 1 << T << FixItHint::CreateInsertion(TypeEndLoc, "*"); T = Context.getObjCObjectPointerType(T); New->setType(T); } // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage // duration shall not be qualified by an address-space qualifier." // Since all parameters have automatic store duration, they can not have // an address space. if (T.getAddressSpace() != 0) { // OpenCL allows function arguments declared to be an array of a type // to be qualified with an address space. if (!(getLangOpts().OpenCL && T->isArrayType())) { Diag(NameLoc, diag::err_arg_with_address_space); New->setInvalidDecl(); } } return New; } void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, SourceLocation LocAfterDecls) { DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); // Verify 6.9.1p6: 'every identifier in the identifier list shall be declared' // for a K&R function. if (!FTI.hasPrototype) { for (int i = FTI.NumParams; i != 0; /* decrement in loop */) { --i; if (FTI.Params[i].Param == nullptr) { SmallString<256> Code; llvm::raw_svector_ostream(Code) << " int " << FTI.Params[i].Ident->getName() << ";\n"; Diag(FTI.Params[i].IdentLoc, diag::ext_param_not_declared) << FTI.Params[i].Ident << FixItHint::CreateInsertion(LocAfterDecls, Code); // Implicitly declare the argument as type 'int' for lack of a better // type. AttributeFactory attrs; DeclSpec DS(attrs); const char* PrevSpec; // unused unsigned DiagID; // unused DS.SetTypeSpecType(DeclSpec::TST_int, FTI.Params[i].IdentLoc, PrevSpec, DiagID, Context.getPrintingPolicy()); // Use the identifier location for the type source range. DS.SetRangeStart(FTI.Params[i].IdentLoc); DS.SetRangeEnd(FTI.Params[i].IdentLoc); Declarator ParamD(DS, Declarator::KNRTypeListContext); ParamD.SetIdentifier(FTI.Params[i].Ident, FTI.Params[i].IdentLoc); FTI.Params[i].Param = ActOnParamDeclarator(S, ParamD); } } } } Decl * Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) { assert(getCurFunctionDecl() == nullptr && "Function parsing confused"); assert(D.isFunctionDeclarator() && "Not a function declarator!"); Scope *ParentScope = FnBodyScope->getParent(); D.setFunctionDefinitionKind(FDK_Definition); Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists); return ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody); } void Sema::ActOnFinishInlineFunctionDef(FunctionDecl *D) { Consumer.HandleInlineFunctionDefinition(D); } static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD, const FunctionDecl*& PossibleZeroParamPrototype) { // Don't warn about invalid declarations. if (FD->isInvalidDecl()) return false; // Or declarations that aren't global. if (!FD->isGlobal()) return false; // Don't warn about C++ member functions. if (isa(FD)) return false; // Don't warn about 'main'. if (FD->isMain()) return false; // Don't warn about inline functions. if (FD->isInlined()) return false; // Don't warn about function templates. if (FD->getDescribedFunctionTemplate()) return false; // Don't warn about function template specializations. if (FD->isFunctionTemplateSpecialization()) return false; // Don't warn for OpenCL kernels. if (FD->hasAttr()) return false; // Don't warn on explicitly deleted functions. if (FD->isDeleted()) return false; bool MissingPrototype = true; for (const FunctionDecl *Prev = FD->getPreviousDecl(); Prev; Prev = Prev->getPreviousDecl()) { // Ignore any declarations that occur in function or method // scope, because they aren't visible from the header. if (Prev->getLexicalDeclContext()->isFunctionOrMethod()) continue; MissingPrototype = !Prev->getType()->isFunctionProtoType(); if (FD->getNumParams() == 0) PossibleZeroParamPrototype = Prev; break; } return MissingPrototype; } void Sema::CheckForFunctionRedefinition(FunctionDecl *FD, const FunctionDecl *EffectiveDefinition, SkipBodyInfo *SkipBody) { const FunctionDecl *Definition = EffectiveDefinition; if (!Definition) if (!FD->isDefined(Definition)) return; if (canRedefineFunction(Definition, getLangOpts())) return; // Don't emit an error when this is redefinition of a typo-corrected // definition. if (TypoCorrectedFunctionDefinitions.count(Definition)) return; // If we don't have a visible definition of the function, and it's inline or // a template, skip the new definition. if (SkipBody && !hasVisibleDefinition(Definition) && (Definition->getFormalLinkage() == InternalLinkage || Definition->isInlined() || Definition->getDescribedFunctionTemplate() || Definition->getNumTemplateParameterLists())) { SkipBody->ShouldSkip = true; if (auto *TD = Definition->getDescribedFunctionTemplate()) makeMergedDefinitionVisible(TD); makeMergedDefinitionVisible(const_cast(Definition)); return; } if (getLangOpts().GNUMode && Definition->isInlineSpecified() && Definition->getStorageClass() == SC_Extern) Diag(FD->getLocation(), diag::err_redefinition_extern_inline) << FD->getDeclName() << getLangOpts().CPlusPlus; else Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); Diag(Definition->getLocation(), diag::note_previous_definition); FD->setInvalidDecl(); } static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator, Sema &S) { CXXRecordDecl *const LambdaClass = CallOperator->getParent(); LambdaScopeInfo *LSI = S.PushLambdaScope(); LSI->CallOperator = CallOperator; LSI->Lambda = LambdaClass; LSI->ReturnType = CallOperator->getReturnType(); const LambdaCaptureDefault LCD = LambdaClass->getLambdaCaptureDefault(); if (LCD == LCD_None) LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None; else if (LCD == LCD_ByCopy) LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval; else if (LCD == LCD_ByRef) LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref; DeclarationNameInfo DNI = CallOperator->getNameInfo(); LSI->IntroducerRange = DNI.getCXXOperatorNameRange(); LSI->Mutable = !CallOperator->isConst(); // Add the captures to the LSI so they can be noted as already // captured within tryCaptureVar. auto I = LambdaClass->field_begin(); for (const auto &C : LambdaClass->captures()) { if (C.capturesVariable()) { VarDecl *VD = C.getCapturedVar(); if (VD->isInitCapture()) S.CurrentInstantiationScope->InstantiatedLocal(VD, VD); QualType CaptureType = VD->getType(); const bool ByRef = C.getCaptureKind() == LCK_ByRef; LSI->addCapture(VD, /*IsBlock*/false, ByRef, /*RefersToEnclosingVariableOrCapture*/true, C.getLocation(), /*EllipsisLoc*/C.isPackExpansion() ? C.getEllipsisLoc() : SourceLocation(), CaptureType, /*Expr*/ nullptr); } else if (C.capturesThis()) { LSI->addThisCapture(/*Nested*/ false, C.getLocation(), /*Expr*/ nullptr, C.getCaptureKind() == LCK_StarThis); } else { LSI->addVLATypeCapture(C.getLocation(), I->getType()); } ++I; } } Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, SkipBodyInfo *SkipBody) { if (!D) return D; FunctionDecl *FD = nullptr; if (FunctionTemplateDecl *FunTmpl = dyn_cast(D)) FD = FunTmpl->getTemplatedDecl(); else FD = cast(D); // Check for defining attributes before the check for redefinition. if (const auto *Attr = FD->getAttr()) { Diag(Attr->getLocation(), diag::err_alias_is_definition) << FD << 0; FD->dropAttr(); FD->setInvalidDecl(); } if (const auto *Attr = FD->getAttr()) { Diag(Attr->getLocation(), diag::err_alias_is_definition) << FD << 1; FD->dropAttr(); FD->setInvalidDecl(); } // See if this is a redefinition. If 'will have body' is already set, then // these checks were already performed when it was set. if (!FD->willHaveBody() && !FD->isLateTemplateParsed()) { CheckForFunctionRedefinition(FD, nullptr, SkipBody); // If we're skipping the body, we're done. Don't enter the scope. if (SkipBody && SkipBody->ShouldSkip) return D; } // Mark this function as "will have a body eventually". This lets users to // call e.g. isInlineDefinitionExternallyVisible while we're still parsing // this function. FD->setWillHaveBody(); // If we are instantiating a generic lambda call operator, push // a LambdaScopeInfo onto the function stack. But use the information // that's already been calculated (ActOnLambdaExpr) to prime the current // LambdaScopeInfo. // When the template operator is being specialized, the LambdaScopeInfo, // has to be properly restored so that tryCaptureVariable doesn't try // and capture any new variables. In addition when calculating potential // captures during transformation of nested lambdas, it is necessary to // have the LSI properly restored. if (isGenericLambdaCallOperatorSpecialization(FD)) { assert(inTemplateInstantiation() && "There should be an active template instantiation on the stack " "when instantiating a generic lambda!"); RebuildLambdaScopeInfo(cast(D), *this); } else { // Enter a new function scope PushFunctionScope(); } // Builtin functions cannot be defined. if (unsigned BuiltinID = FD->getBuiltinID()) { if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) && !Context.BuiltinInfo.isPredefinedRuntimeFunction(BuiltinID)) { Diag(FD->getLocation(), diag::err_builtin_definition) << FD; FD->setInvalidDecl(); } } // The return type of a function definition must be complete // (C99 6.9.1p3, C++ [dcl.fct]p6). QualType ResultType = FD->getReturnType(); if (!ResultType->isDependentType() && !ResultType->isVoidType() && !FD->isInvalidDecl() && RequireCompleteType(FD->getLocation(), ResultType, diag::err_func_def_incomplete_result)) FD->setInvalidDecl(); if (FnBodyScope) PushDeclContext(FnBodyScope, FD); // Check the validity of our function parameters CheckParmsForFunctionDef(FD->parameters(), /*CheckParameterNames=*/true); // Add non-parameter declarations already in the function to the current // scope. if (FnBodyScope) { for (Decl *NPD : FD->decls()) { auto *NonParmDecl = dyn_cast(NPD); if (!NonParmDecl) continue; assert(!isa(NonParmDecl) && "parameters should not be in newly created FD yet"); // If the decl has a name, make it accessible in the current scope. if (NonParmDecl->getDeclName()) PushOnScopeChains(NonParmDecl, FnBodyScope, /*AddToContext=*/false); // Similarly, dive into enums and fish their constants out, making them // accessible in this scope. if (auto *ED = dyn_cast(NonParmDecl)) { for (auto *EI : ED->enumerators()) PushOnScopeChains(EI, FnBodyScope, /*AddToContext=*/false); } } } // Introduce our parameters into the function scope for (auto Param : FD->parameters()) { Param->setOwningFunction(FD); // If this has an identifier, add it to the scope stack. if (Param->getIdentifier() && FnBodyScope) { CheckShadow(FnBodyScope, Param); PushOnScopeChains(Param, FnBodyScope); } } // Ensure that the function's exception specification is instantiated. if (const FunctionProtoType *FPT = FD->getType()->getAs()) ResolveExceptionSpec(D->getLocation(), FPT); // dllimport cannot be applied to non-inline function definitions. if (FD->hasAttr() && !FD->isInlined() && !FD->isTemplateInstantiation()) { assert(!FD->hasAttr()); Diag(FD->getLocation(), diag::err_attribute_dllimport_function_definition); FD->setInvalidDecl(); return D; } // We want to attach documentation to original Decl (which might be // a function template). ActOnDocumentableDecl(D); if (getCurLexicalContext()->isObjCContainer() && getCurLexicalContext()->getDeclKind() != Decl::ObjCCategoryImpl && getCurLexicalContext()->getDeclKind() != Decl::ObjCImplementation) Diag(FD->getLocation(), diag::warn_function_def_in_objc_container); return D; } /// \brief Given the set of return statements within a function body, /// compute the variables that are subject to the named return value /// optimization. /// /// Each of the variables that is subject to the named return value /// optimization will be marked as NRVO variables in the AST, and any /// return statement that has a marked NRVO variable as its NRVO candidate can /// use the named return value optimization. /// /// This function applies a very simplistic algorithm for NRVO: if every return /// statement in the scope of a variable has the same NRVO candidate, that /// candidate is an NRVO variable. void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) { ReturnStmt **Returns = Scope->Returns.data(); for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) { if (const VarDecl *NRVOCandidate = Returns[I]->getNRVOCandidate()) { if (!NRVOCandidate->isNRVOVariable()) Returns[I]->setNRVOCandidate(nullptr); } } } bool Sema::canDelayFunctionBody(const Declarator &D) { // We can't delay parsing the body of a constexpr function template (yet). if (D.getDeclSpec().isConstexprSpecified()) return false; // We can't delay parsing the body of a function template with a deduced // return type (yet). if (D.getDeclSpec().hasAutoTypeSpec()) { // If the placeholder introduces a non-deduced trailing return type, // we can still delay parsing it. if (D.getNumTypeObjects()) { const auto &Outer = D.getTypeObject(D.getNumTypeObjects() - 1); if (Outer.Kind == DeclaratorChunk::Function && Outer.Fun.hasTrailingReturnType()) { QualType Ty = GetTypeFromParser(Outer.Fun.getTrailingReturnType()); return Ty.isNull() || !Ty->isUndeducedType(); } } return false; } return true; } bool Sema::canSkipFunctionBody(Decl *D) { // We cannot skip the body of a function (or function template) which is // constexpr, since we may need to evaluate its body in order to parse the // rest of the file. // We cannot skip the body of a function with an undeduced return type, // because any callers of that function need to know the type. if (const FunctionDecl *FD = D->getAsFunction()) if (FD->isConstexpr() || FD->getReturnType()->isUndeducedType()) return false; return Consumer.shouldSkipFunctionBody(D); } Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) { if (FunctionDecl *FD = dyn_cast_or_null(Decl)) FD->setHasSkippedBody(); else if (ObjCMethodDecl *MD = dyn_cast_or_null(Decl)) MD->setHasSkippedBody(); return Decl; } Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) { return ActOnFinishFunctionBody(D, BodyArg, false); } Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, bool IsInstantiation) { FunctionDecl *FD = dcl ? dcl->getAsFunction() : nullptr; sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); sema::AnalysisBasedWarnings::Policy *ActivePolicy = nullptr; if (getLangOpts().CoroutinesTS && getCurFunction()->isCoroutine()) CheckCompletedCoroutineBody(FD, Body); if (FD) { FD->setBody(Body); FD->setWillHaveBody(false); if (getLangOpts().CPlusPlus14) { if (!FD->isInvalidDecl() && Body && !FD->isDependentContext() && FD->getReturnType()->isUndeducedType()) { // If the function has a deduced result type but contains no 'return' // statements, the result type as written must be exactly 'auto', and // the deduced result type is 'void'. if (!FD->getReturnType()->getAs()) { Diag(dcl->getLocation(), diag::err_auto_fn_no_return_but_not_auto) << FD->getReturnType(); FD->setInvalidDecl(); } else { // Substitute 'void' for the 'auto' in the type. TypeLoc ResultType = getReturnTypeLoc(FD); Context.adjustDeducedFunctionResultType( FD, SubstAutoType(ResultType.getType(), Context.VoidTy)); } } } else if (getLangOpts().CPlusPlus11 && isLambdaCallOperator(FD)) { // In C++11, we don't use 'auto' deduction rules for lambda call // operators because we don't support return type deduction. auto *LSI = getCurLambda(); if (LSI->HasImplicitReturnType) { deduceClosureReturnType(*LSI); // C++11 [expr.prim.lambda]p4: // [...] if there are no return statements in the compound-statement // [the deduced type is] the type void QualType RetType = LSI->ReturnType.isNull() ? Context.VoidTy : LSI->ReturnType; // Update the return type to the deduced type. const FunctionProtoType *Proto = FD->getType()->getAs(); FD->setType(Context.getFunctionType(RetType, Proto->getParamTypes(), Proto->getExtProtoInfo())); } } // The only way to be included in UndefinedButUsed is if there is an // ODR use before the definition. Avoid the expensive map lookup if this // is the first declaration. if (!FD->isFirstDecl() && FD->getPreviousDecl()->isUsed()) { if (!FD->isExternallyVisible()) UndefinedButUsed.erase(FD); else if (FD->isInlined() && !LangOpts.GNUInline && (!FD->getPreviousDecl()->hasAttr())) UndefinedButUsed.erase(FD); } // If the function implicitly returns zero (like 'main') or is naked, // don't complain about missing return statements. if (FD->hasImplicitReturnZero() || FD->hasAttr()) WP.disableCheckFallThrough(); // MSVC permits the use of pure specifier (=0) on function definition, // defined at class scope, warn about this non-standard construct. if (getLangOpts().MicrosoftExt && FD->isPure() && FD->isCanonicalDecl()) Diag(FD->getLocation(), diag::ext_pure_function_definition); if (!FD->isInvalidDecl()) { // Don't diagnose unused parameters of defaulted or deleted functions. if (!FD->isDeleted() && !FD->isDefaulted()) DiagnoseUnusedParameters(FD->parameters()); DiagnoseSizeOfParametersAndReturnValue(FD->parameters(), FD->getReturnType(), FD); // If this is a structor, we need a vtable. if (CXXConstructorDecl *Constructor = dyn_cast(FD)) MarkVTableUsed(FD->getLocation(), Constructor->getParent()); else if (CXXDestructorDecl *Destructor = dyn_cast(FD)) MarkVTableUsed(FD->getLocation(), Destructor->getParent()); // Try to apply the named return value optimization. We have to check // if we can do this here because lambdas keep return statements around // to deduce an implicit return type. if (getLangOpts().CPlusPlus && FD->getReturnType()->isRecordType() && !FD->isDependentContext()) computeNRVO(Body, getCurFunction()); } // GNU warning -Wmissing-prototypes: // Warn if a global function is defined without a previous // prototype declaration. This warning is issued even if the // definition itself provides a prototype. The aim is to detect // global functions that fail to be declared in header files. const FunctionDecl *PossibleZeroParamPrototype = nullptr; if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) { Diag(FD->getLocation(), diag::warn_missing_prototype) << FD; if (PossibleZeroParamPrototype) { // We found a declaration that is not a prototype, // but that could be a zero-parameter prototype if (TypeSourceInfo *TI = PossibleZeroParamPrototype->getTypeSourceInfo()) { TypeLoc TL = TI->getTypeLoc(); if (FunctionNoProtoTypeLoc FTL = TL.getAs()) Diag(PossibleZeroParamPrototype->getLocation(), diag::note_declaration_not_a_prototype) << PossibleZeroParamPrototype << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void"); } } // GNU warning -Wstrict-prototypes // Warn if K&R function is defined without a previous declaration. // This warning is issued only if the definition itself does not provide // a prototype. Only K&R definitions do not provide a prototype. // An empty list in a function declarator that is part of a definition // of that function specifies that the function has no parameters // (C99 6.7.5.3p14) if (!FD->hasWrittenPrototype() && FD->getNumParams() > 0 && !LangOpts.CPlusPlus) { TypeSourceInfo *TI = FD->getTypeSourceInfo(); TypeLoc TL = TI->getTypeLoc(); FunctionTypeLoc FTL = TL.getAsAdjusted(); Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 2; } } if (auto *MD = dyn_cast(FD)) { const CXXMethodDecl *KeyFunction; if (MD->isOutOfLine() && (MD = MD->getCanonicalDecl()) && MD->isVirtual() && (KeyFunction = Context.getCurrentKeyFunction(MD->getParent())) && MD == KeyFunction->getCanonicalDecl()) { // Update the key-function state if necessary for this ABI. if (FD->isInlined() && !Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline()) { Context.setNonKeyFunction(MD); // If the newly-chosen key function is already defined, then we // need to mark the vtable as used retroactively. KeyFunction = Context.getCurrentKeyFunction(MD->getParent()); const FunctionDecl *Definition; if (KeyFunction && KeyFunction->isDefined(Definition)) MarkVTableUsed(Definition->getLocation(), MD->getParent(), true); } else { // We just defined they key function; mark the vtable as used. MarkVTableUsed(FD->getLocation(), MD->getParent(), true); } } } assert((FD == getCurFunctionDecl() || getCurLambda()->CallOperator == FD) && "Function parsing confused"); } else if (ObjCMethodDecl *MD = dyn_cast_or_null(dcl)) { assert(MD == getCurMethodDecl() && "Method parsing confused"); MD->setBody(Body); if (!MD->isInvalidDecl()) { DiagnoseUnusedParameters(MD->parameters()); DiagnoseSizeOfParametersAndReturnValue(MD->parameters(), MD->getReturnType(), MD); if (Body) computeNRVO(Body, getCurFunction()); } if (getCurFunction()->ObjCShouldCallSuper) { Diag(MD->getLocEnd(), diag::warn_objc_missing_super_call) << MD->getSelector().getAsString(); getCurFunction()->ObjCShouldCallSuper = false; } if (getCurFunction()->ObjCWarnForNoDesignatedInitChain) { const ObjCMethodDecl *InitMethod = nullptr; bool isDesignated = MD->isDesignatedInitializerForTheInterface(&InitMethod); assert(isDesignated && InitMethod); (void)isDesignated; auto superIsNSObject = [&](const ObjCMethodDecl *MD) { auto IFace = MD->getClassInterface(); if (!IFace) return false; auto SuperD = IFace->getSuperClass(); if (!SuperD) return false; return SuperD->getIdentifier() == NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject); }; // Don't issue this warning for unavailable inits or direct subclasses // of NSObject. if (!MD->isUnavailable() && !superIsNSObject(MD)) { Diag(MD->getLocation(), diag::warn_objc_designated_init_missing_super_call); Diag(InitMethod->getLocation(), diag::note_objc_designated_init_marked_here); } getCurFunction()->ObjCWarnForNoDesignatedInitChain = false; } if (getCurFunction()->ObjCWarnForNoInitDelegation) { // Don't issue this warning for unavaialable inits. if (!MD->isUnavailable()) Diag(MD->getLocation(), diag::warn_objc_secondary_init_missing_init_call); getCurFunction()->ObjCWarnForNoInitDelegation = false; } } else { return nullptr; } if (Body && getCurFunction()->HasPotentialAvailabilityViolations) DiagnoseUnguardedAvailabilityViolations(dcl); assert(!getCurFunction()->ObjCShouldCallSuper && "This should only be set for ObjC methods, which should have been " "handled in the block above."); // Verify and clean out per-function state. if (Body && (!FD || !FD->isDefaulted())) { // C++ constructors that have function-try-blocks can't have return // statements in the handlers of that block. (C++ [except.handle]p14) // Verify this. if (FD && isa(FD) && isa(Body)) DiagnoseReturnInConstructorExceptionHandler(cast(Body)); // Verify that gotos and switch cases don't jump into scopes illegally. if (getCurFunction()->NeedsScopeChecking() && !PP.isCodeCompletionEnabled()) DiagnoseInvalidJumps(Body); if (CXXDestructorDecl *Destructor = dyn_cast(dcl)) { if (!Destructor->getParent()->isDependentType()) CheckDestructor(Destructor); MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(), Destructor->getParent()); } // If any errors have occurred, clear out any temporaries that may have // been leftover. This ensures that these temporaries won't be picked up for // deletion in some later function. if (getDiagnostics().hasErrorOccurred() || getDiagnostics().getSuppressAllDiagnostics()) { DiscardCleanupsInEvaluationContext(); } if (!getDiagnostics().hasUncompilableErrorOccurred() && !isa(dcl)) { // Since the body is valid, issue any analysis-based warnings that are // enabled. ActivePolicy = &WP; } if (!IsInstantiation && FD && FD->isConstexpr() && !FD->isInvalidDecl() && (!CheckConstexprFunctionDecl(FD) || !CheckConstexprFunctionBody(FD, Body))) FD->setInvalidDecl(); if (FD && FD->hasAttr()) { for (const Stmt *S : Body->children()) { // Allow local register variables without initializer as they don't // require prologue. bool RegisterVariables = false; if (auto *DS = dyn_cast(S)) { for (const auto *Decl : DS->decls()) { if (const auto *Var = dyn_cast(Decl)) { RegisterVariables = Var->hasAttr() && !Var->hasInit(); if (!RegisterVariables) break; } } } if (RegisterVariables) continue; if (!isa(S) && !isa(S)) { Diag(S->getLocStart(), diag::err_non_asm_stmt_in_naked_function); Diag(FD->getAttr()->getLocation(), diag::note_attribute); FD->setInvalidDecl(); break; } } } assert(ExprCleanupObjects.size() == ExprEvalContexts.back().NumCleanupObjects && "Leftover temporaries in function"); assert(!Cleanup.exprNeedsCleanups() && "Unaccounted cleanups in function"); assert(MaybeODRUseExprs.empty() && "Leftover expressions for odr-use checking"); } if (!IsInstantiation) PopDeclContext(); PopFunctionScopeInfo(ActivePolicy, dcl); // If any errors have occurred, clear out any temporaries that may have // been leftover. This ensures that these temporaries won't be picked up for // deletion in some later function. if (getDiagnostics().hasErrorOccurred()) { DiscardCleanupsInEvaluationContext(); } return dcl; } /// When we finish delayed parsing of an attribute, we must attach it to the /// relevant Decl. void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D, ParsedAttributes &Attrs) { // Always attach attributes to the underlying decl. if (TemplateDecl *TD = dyn_cast(D)) D = TD->getTemplatedDecl(); ProcessDeclAttributeList(S, D, Attrs.getList()); if (CXXMethodDecl *Method = dyn_cast_or_null(D)) if (Method->isStatic()) checkThisInStaticMemberFunctionAttributes(Method); } /// ImplicitlyDefineFunction - An undeclared identifier was used in a function /// call, forming a call to an implicitly defined function (per C99 6.5.1p2). NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, Scope *S) { // Before we produce a declaration for an implicitly defined // function, see whether there was a locally-scoped declaration of // this name as a function or variable. If so, use that // (non-visible) declaration, and complain about it. if (NamedDecl *ExternCPrev = findLocallyScopedExternCDecl(&II)) { Diag(Loc, diag::warn_use_out_of_scope_declaration) << ExternCPrev; Diag(ExternCPrev->getLocation(), diag::note_previous_declaration); return ExternCPrev; } // Extension in C99. Legal in C90, but warn about it. unsigned diag_id; if (II.getName().startswith("__builtin_")) diag_id = diag::warn_builtin_unknown; // OpenCL v2.0 s6.9.u - Implicit function declaration is not supported. else if (getLangOpts().OpenCL) diag_id = diag::err_opencl_implicit_function_decl; else if (getLangOpts().C99) diag_id = diag::ext_implicit_function_decl; else diag_id = diag::warn_implicit_function_decl; Diag(Loc, diag_id) << &II; // Because typo correction is expensive, only do it if the implicit // function declaration is going to be treated as an error. if (Diags.getDiagnosticLevel(diag_id, Loc) >= DiagnosticsEngine::Error) { TypoCorrection Corrected; if (S && (Corrected = CorrectTypo( DeclarationNameInfo(&II, Loc), LookupOrdinaryName, S, nullptr, llvm::make_unique>(), CTK_NonError))) diagnoseTypo(Corrected, PDiag(diag::note_function_suggestion), /*ErrorRecovery*/false); } // Set a Declarator for the implicit definition: int foo(); const char *Dummy; AttributeFactory attrFactory; DeclSpec DS(attrFactory); unsigned DiagID; bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID, Context.getPrintingPolicy()); (void)Error; // Silence warning. assert(!Error && "Error setting up implicit decl!"); SourceLocation NoLoc; Declarator D(DS, Declarator::BlockContext); D.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/false, /*IsAmbiguous=*/false, /*LParenLoc=*/NoLoc, /*Params=*/nullptr, /*NumParams=*/0, /*EllipsisLoc=*/NoLoc, /*RParenLoc=*/NoLoc, /*TypeQuals=*/0, /*RefQualifierIsLvalueRef=*/true, /*RefQualifierLoc=*/NoLoc, /*ConstQualifierLoc=*/NoLoc, /*VolatileQualifierLoc=*/NoLoc, /*RestrictQualifierLoc=*/NoLoc, /*MutableLoc=*/NoLoc, EST_None, /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, /*ExceptionSpecTokens=*/nullptr, /*DeclsInPrototype=*/None, Loc, Loc, D), DS.getAttributes(), SourceLocation()); D.SetIdentifier(&II, Loc); // Insert this function into translation-unit scope. DeclContext *PrevDC = CurContext; CurContext = Context.getTranslationUnitDecl(); FunctionDecl *FD = cast(ActOnDeclarator(TUScope, D)); FD->setImplicit(); CurContext = PrevDC; AddKnownFunctionAttributes(FD); return FD; } /// \brief Adds any function attributes that we know a priori based on /// the declaration of this function. /// /// These attributes can apply both to implicitly-declared builtins /// (like __builtin___printf_chk) or to library-declared functions /// like NSLog or printf. /// /// We need to check for duplicate attributes both here and where user-written /// attributes are applied to declarations. void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { if (FD->isInvalidDecl()) return; // If this is a built-in function, map its builtin attributes to // actual attributes. if (unsigned BuiltinID = FD->getBuiltinID()) { // Handle printf-formatting attributes. unsigned FormatIdx; bool HasVAListArg; if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) { if (!FD->hasAttr()) { const char *fmt = "printf"; unsigned int NumParams = FD->getNumParams(); if (FormatIdx < NumParams && // NumParams may be 0 (e.g. vfprintf) FD->getParamDecl(FormatIdx)->getType()->isObjCObjectPointerType()) fmt = "NSString"; FD->addAttr(FormatAttr::CreateImplicit(Context, &Context.Idents.get(fmt), FormatIdx+1, HasVAListArg ? 0 : FormatIdx+2, FD->getLocation())); } } if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx, HasVAListArg)) { if (!FD->hasAttr()) FD->addAttr(FormatAttr::CreateImplicit(Context, &Context.Idents.get("scanf"), FormatIdx+1, HasVAListArg ? 0 : FormatIdx+2, FD->getLocation())); } // Mark const if we don't care about errno and that is the only // thing preventing the function from being const. This allows // IRgen to use LLVM intrinsics for such functions. if (!getLangOpts().MathErrno && Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) { if (!FD->hasAttr()) FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation())); } if (Context.BuiltinInfo.isReturnsTwice(BuiltinID) && !FD->hasAttr()) FD->addAttr(ReturnsTwiceAttr::CreateImplicit(Context, FD->getLocation())); if (Context.BuiltinInfo.isNoThrow(BuiltinID) && !FD->hasAttr()) FD->addAttr(NoThrowAttr::CreateImplicit(Context, FD->getLocation())); if (Context.BuiltinInfo.isPure(BuiltinID) && !FD->hasAttr()) FD->addAttr(PureAttr::CreateImplicit(Context, FD->getLocation())); if (Context.BuiltinInfo.isConst(BuiltinID) && !FD->hasAttr()) FD->addAttr(ConstAttr::CreateImplicit(Context, FD->getLocation())); if (getLangOpts().CUDA && Context.BuiltinInfo.isTSBuiltin(BuiltinID) && !FD->hasAttr() && !FD->hasAttr()) { // Add the appropriate attribute, depending on the CUDA compilation mode // and which target the builtin belongs to. For example, during host // compilation, aux builtins are __device__, while the rest are __host__. if (getLangOpts().CUDAIsDevice != Context.BuiltinInfo.isAuxBuiltinID(BuiltinID)) FD->addAttr(CUDADeviceAttr::CreateImplicit(Context, FD->getLocation())); else FD->addAttr(CUDAHostAttr::CreateImplicit(Context, FD->getLocation())); } } // If C++ exceptions are enabled but we are told extern "C" functions cannot // throw, add an implicit nothrow attribute to any extern "C" function we come // across. if (getLangOpts().CXXExceptions && getLangOpts().ExternCNoUnwind && FD->isExternC() && !FD->hasAttr()) { const auto *FPT = FD->getType()->getAs(); if (!FPT || FPT->getExceptionSpecType() == EST_None) FD->addAttr(NoThrowAttr::CreateImplicit(Context, FD->getLocation())); } IdentifierInfo *Name = FD->getIdentifier(); if (!Name) return; if ((!getLangOpts().CPlusPlus && FD->getDeclContext()->isTranslationUnit()) || (isa(FD->getDeclContext()) && cast(FD->getDeclContext())->getLanguage() == LinkageSpecDecl::lang_c)) { // Okay: this could be a libc/libm/Objective-C function we know // about. } else return; if (Name->isStr("asprintf") || Name->isStr("vasprintf")) { // FIXME: asprintf and vasprintf aren't C99 functions. Should they be // target-specific builtins, perhaps? if (!FD->hasAttr()) FD->addAttr(FormatAttr::CreateImplicit(Context, &Context.Idents.get("printf"), 2, Name->isStr("vasprintf") ? 0 : 3, FD->getLocation())); } if (Name->isStr("__CFStringMakeConstantString")) { // We already have a __builtin___CFStringMakeConstantString, // but builds that use -fno-constant-cfstrings don't go through that. if (!FD->hasAttr()) FD->addAttr(FormatArgAttr::CreateImplicit(Context, 1, FD->getLocation())); } } TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, TypeSourceInfo *TInfo) { assert(D.getIdentifier() && "Wrong callback for declspec without declarator"); assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); if (!TInfo) { assert(D.isInvalidType() && "no declarator info for valid type"); TInfo = Context.getTrivialTypeSourceInfo(T); } // Scope manipulation handled by caller. TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext, D.getLocStart(), D.getIdentifierLoc(), D.getIdentifier(), TInfo); // Bail out immediately if we have an invalid declaration. if (D.isInvalidType()) { NewTD->setInvalidDecl(); return NewTD; } if (D.getDeclSpec().isModulePrivateSpecified()) { if (CurContext->isFunctionOrMethod()) Diag(NewTD->getLocation(), diag::err_module_private_local) << 2 << NewTD->getDeclName() << SourceRange(D.getDeclSpec().getModulePrivateSpecLoc()) << FixItHint::CreateRemoval(D.getDeclSpec().getModulePrivateSpecLoc()); else NewTD->setModulePrivate(); } // C++ [dcl.typedef]p8: // If the typedef declaration defines an unnamed class (or // enum), the first typedef-name declared by the declaration // to be that class type (or enum type) is used to denote the // class type (or enum type) for linkage purposes only. // We need to check whether the type was declared in the declaration. switch (D.getDeclSpec().getTypeSpecType()) { case TST_enum: case TST_struct: case TST_interface: case TST_union: case TST_class: { TagDecl *tagFromDeclSpec = cast(D.getDeclSpec().getRepAsDecl()); setTagNameForLinkagePurposes(tagFromDeclSpec, NewTD); break; } default: break; } return NewTD; } /// \brief Check that this is a valid underlying type for an enum declaration. bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) { SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); QualType T = TI->getType(); if (T->isDependentType()) return false; if (const BuiltinType *BT = T->getAs()) if (BT->isInteger()) return false; Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << T; return true; } /// Check whether this is a valid redeclaration of a previous enumeration. /// \return true if the redeclaration was invalid. bool Sema::CheckEnumRedeclaration( SourceLocation EnumLoc, bool IsScoped, QualType EnumUnderlyingTy, bool EnumUnderlyingIsImplicit, const EnumDecl *Prev) { bool IsFixed = !EnumUnderlyingTy.isNull(); if (IsScoped != Prev->isScoped()) { Diag(EnumLoc, diag::err_enum_redeclare_scoped_mismatch) << Prev->isScoped(); Diag(Prev->getLocation(), diag::note_previous_declaration); return true; } if (IsFixed && Prev->isFixed()) { if (!EnumUnderlyingTy->isDependentType() && !Prev->getIntegerType()->isDependentType() && !Context.hasSameUnqualifiedType(EnumUnderlyingTy, Prev->getIntegerType())) { // TODO: Highlight the underlying type of the redeclaration. Diag(EnumLoc, diag::err_enum_redeclare_type_mismatch) << EnumUnderlyingTy << Prev->getIntegerType(); Diag(Prev->getLocation(), diag::note_previous_declaration) << Prev->getIntegerTypeRange(); return true; } } else if (IsFixed && !Prev->isFixed() && EnumUnderlyingIsImplicit) { ; } else if (!IsFixed && Prev->isFixed() && !Prev->getIntegerTypeSourceInfo()) { ; } else if (IsFixed != Prev->isFixed()) { Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch) << Prev->isFixed(); Diag(Prev->getLocation(), diag::note_previous_declaration); return true; } return false; } /// \brief Get diagnostic %select index for tag kind for /// redeclaration diagnostic message. /// WARNING: Indexes apply to particular diagnostics only! /// /// \returns diagnostic %select index. static unsigned getRedeclDiagFromTagKind(TagTypeKind Tag) { switch (Tag) { case TTK_Struct: return 0; case TTK_Interface: return 1; case TTK_Class: return 2; default: llvm_unreachable("Invalid tag kind for redecl diagnostic!"); } } /// \brief Determine if tag kind is a class-key compatible with /// class for redeclaration (class, struct, or __interface). /// /// \returns true iff the tag kind is compatible. static bool isClassCompatTagKind(TagTypeKind Tag) { return Tag == TTK_Struct || Tag == TTK_Class || Tag == TTK_Interface; } Sema::NonTagKind Sema::getNonTagTypeDeclKind(const Decl *PrevDecl, TagTypeKind TTK) { if (isa(PrevDecl)) return NTK_Typedef; else if (isa(PrevDecl)) return NTK_TypeAlias; else if (isa(PrevDecl)) return NTK_Template; else if (isa(PrevDecl)) return NTK_TypeAliasTemplate; else if (isa(PrevDecl)) return NTK_TemplateTemplateArgument; switch (TTK) { case TTK_Struct: case TTK_Interface: case TTK_Class: return getLangOpts().CPlusPlus ? NTK_NonClass : NTK_NonStruct; case TTK_Union: return NTK_NonUnion; case TTK_Enum: return NTK_NonEnum; } llvm_unreachable("invalid TTK"); } /// \brief Determine whether a tag with a given kind is acceptable /// as a redeclaration of the given tag declaration. /// /// \returns true if the new tag kind is acceptable, false otherwise. bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, TagTypeKind NewTag, bool isDefinition, SourceLocation NewTagLoc, const IdentifierInfo *Name) { // C++ [dcl.type.elab]p3: // The class-key or enum keyword present in the // elaborated-type-specifier shall agree in kind with the // declaration to which the name in the elaborated-type-specifier // refers. This rule also applies to the form of // elaborated-type-specifier that declares a class-name or // friend class since it can be construed as referring to the // definition of the class. Thus, in any // elaborated-type-specifier, the enum keyword shall be used to // refer to an enumeration (7.2), the union class-key shall be // used to refer to a union (clause 9), and either the class or // struct class-key shall be used to refer to a class (clause 9) // declared using the class or struct class-key. TagTypeKind OldTag = Previous->getTagKind(); if (!isDefinition || !isClassCompatTagKind(NewTag)) if (OldTag == NewTag) return true; if (isClassCompatTagKind(OldTag) && isClassCompatTagKind(NewTag)) { // Warn about the struct/class tag mismatch. bool isTemplate = false; if (const CXXRecordDecl *Record = dyn_cast(Previous)) isTemplate = Record->getDescribedClassTemplate(); if (inTemplateInstantiation()) { // In a template instantiation, do not offer fix-its for tag mismatches // since they usually mess up the template instead of fixing the problem. Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch) << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name << getRedeclDiagFromTagKind(OldTag); return true; } if (isDefinition) { // On definitions, check previous tags and issue a fix-it for each // one that doesn't match the current tag. if (Previous->getDefinition()) { // Don't suggest fix-its for redefinitions. return true; } bool previousMismatch = false; for (auto I : Previous->redecls()) { if (I->getTagKind() != NewTag) { if (!previousMismatch) { previousMismatch = true; Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch) << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name << getRedeclDiagFromTagKind(I->getTagKind()); } Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion) << getRedeclDiagFromTagKind(NewTag) << FixItHint::CreateReplacement(I->getInnerLocStart(), TypeWithKeyword::getTagTypeKindName(NewTag)); } } return true; } // Check for a previous definition. If current tag and definition // are same type, do nothing. If no definition, but disagree with // with previous tag type, give a warning, but no fix-it. const TagDecl *Redecl = Previous->getDefinition() ? Previous->getDefinition() : Previous; if (Redecl->getTagKind() == NewTag) { return true; } Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch) << getRedeclDiagFromTagKind(NewTag) << isTemplate << Name << getRedeclDiagFromTagKind(OldTag); Diag(Redecl->getLocation(), diag::note_previous_use); // If there is a previous definition, suggest a fix-it. if (Previous->getDefinition()) { Diag(NewTagLoc, diag::note_struct_class_suggestion) << getRedeclDiagFromTagKind(Redecl->getTagKind()) << FixItHint::CreateReplacement(SourceRange(NewTagLoc), TypeWithKeyword::getTagTypeKindName(Redecl->getTagKind())); } return true; } return false; } /// Add a minimal nested name specifier fixit hint to allow lookup of a tag name /// from an outer enclosing namespace or file scope inside a friend declaration. /// This should provide the commented out code in the following snippet: /// namespace N { /// struct X; /// namespace M { /// struct Y { friend struct /*N::*/ X; }; /// } /// } static FixItHint createFriendTagNNSFixIt(Sema &SemaRef, NamedDecl *ND, Scope *S, SourceLocation NameLoc) { // While the decl is in a namespace, do repeated lookup of that name and see // if we get the same namespace back. If we do not, continue until // translation unit scope, at which point we have a fully qualified NNS. SmallVector Namespaces; DeclContext *DC = ND->getDeclContext()->getRedeclContext(); for (; !DC->isTranslationUnit(); DC = DC->getParent()) { // This tag should be declared in a namespace, which can only be enclosed by // other namespaces. Bail if there's an anonymous namespace in the chain. NamespaceDecl *Namespace = dyn_cast(DC); if (!Namespace || Namespace->isAnonymousNamespace()) return FixItHint(); IdentifierInfo *II = Namespace->getIdentifier(); Namespaces.push_back(II); NamedDecl *Lookup = SemaRef.LookupSingleName( S, II, NameLoc, Sema::LookupNestedNameSpecifierName); if (Lookup == Namespace) break; } // Once we have all the namespaces, reverse them to go outermost first, and // build an NNS. SmallString<64> Insertion; llvm::raw_svector_ostream OS(Insertion); if (DC->isTranslationUnit()) OS << "::"; std::reverse(Namespaces.begin(), Namespaces.end()); for (auto *II : Namespaces) OS << II->getName() << "::"; return FixItHint::CreateInsertion(NameLoc, Insertion); } /// \brief Determine whether a tag originally declared in context \p OldDC can /// be redeclared with an unqualfied name in \p NewDC (assuming name lookup /// found a declaration in \p OldDC as a previous decl, perhaps through a /// using-declaration). static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC, DeclContext *NewDC) { OldDC = OldDC->getRedeclContext(); NewDC = NewDC->getRedeclContext(); if (OldDC->Equals(NewDC)) return true; // In MSVC mode, we allow a redeclaration if the contexts are related (either // encloses the other). if (S.getLangOpts().MSVCCompat && (OldDC->Encloses(NewDC) || NewDC->Encloses(OldDC))) return true; return false; } /// \brief This is invoked when we see 'struct foo' or 'struct {'. In the /// former case, Name will be non-null. In the later case, Name will be null. /// TagSpec indicates what kind of tag this is. TUK indicates whether this is a /// reference/declaration/definition of a tag. /// /// \param IsTypeSpecifier \c true if this is a type-specifier (or /// trailing-type-specifier) other than one in an alias-declaration. /// /// \param SkipBody If non-null, will be set to indicate if the caller should /// skip the definition of this tag and treat it as if it were a declaration. Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, AccessSpecifier AS, SourceLocation ModulePrivateLoc, MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, bool &IsDependent, SourceLocation ScopedEnumKWLoc, bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, bool IsTypeSpecifier, bool IsTemplateParamOrArg, SkipBodyInfo *SkipBody) { // If this is not a definition, it must have a name. IdentifierInfo *OrigName = Name; assert((Name != nullptr || TUK == TUK_Definition) && "Nameless record must be a definition!"); assert(TemplateParameterLists.size() == 0 || TUK != TUK_Reference); OwnedDecl = false; TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); bool ScopedEnum = ScopedEnumKWLoc.isValid(); // FIXME: Check member specializations more carefully. bool isMemberSpecialization = false; bool Invalid = false; // We only need to do this matching if we have template parameters // or a scope specifier, which also conveniently avoids this work // for non-C++ cases. if (TemplateParameterLists.size() > 0 || (SS.isNotEmpty() && TUK != TUK_Reference)) { if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( KWLoc, NameLoc, SS, nullptr, TemplateParameterLists, TUK == TUK_Friend, isMemberSpecialization, Invalid)) { if (Kind == TTK_Enum) { Diag(KWLoc, diag::err_enum_template); return nullptr; } if (TemplateParams->size() > 0) { // This is a declaration or definition of a class template (which may // be a member of another template). if (Invalid) return nullptr; OwnedDecl = false; DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attr, TemplateParams, AS, ModulePrivateLoc, /*FriendLoc*/SourceLocation(), TemplateParameterLists.size()-1, TemplateParameterLists.data(), SkipBody); return Result.get(); } else { // The "template<>" header is extraneous. Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams) << TypeWithKeyword::getTagTypeKindName(Kind) << Name; isMemberSpecialization = true; } } } // Figure out the underlying type if this a enum declaration. We need to do // this early, because it's needed to detect if this is an incompatible // redeclaration. llvm::PointerUnion EnumUnderlying; bool EnumUnderlyingIsImplicit = false; if (Kind == TTK_Enum) { if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum)) // No underlying type explicitly specified, or we failed to parse the // type, default to int. EnumUnderlying = Context.IntTy.getTypePtr(); else if (UnderlyingType.get()) { // C++0x 7.2p2: The type-specifier-seq of an enum-base shall name an // integral type; any cv-qualification is ignored. TypeSourceInfo *TI = nullptr; GetTypeFromParser(UnderlyingType.get(), &TI); EnumUnderlying = TI; if (CheckEnumUnderlyingType(TI)) // Recover by falling back to int. EnumUnderlying = Context.IntTy.getTypePtr(); if (DiagnoseUnexpandedParameterPack(TI->getTypeLoc().getBeginLoc(), TI, UPPC_FixedUnderlyingType)) EnumUnderlying = Context.IntTy.getTypePtr(); } else if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { if (getLangOpts().MSVCCompat || TUK == TUK_Definition) { // Microsoft enums are always of int type. EnumUnderlying = Context.IntTy.getTypePtr(); EnumUnderlyingIsImplicit = true; } } } DeclContext *SearchDC = CurContext; DeclContext *DC = CurContext; bool isStdBadAlloc = false; bool isStdAlignValT = false; RedeclarationKind Redecl = ForRedeclaration; if (TUK == TUK_Friend || TUK == TUK_Reference) Redecl = NotForRedeclaration; /// Create a new tag decl in C/ObjC. Since the ODR-like semantics for ObjC/C /// implemented asks for structural equivalence checking, the returned decl /// here is passed back to the parser, allowing the tag body to be parsed. auto createTagFromNewDecl = [&]() -> TagDecl * { assert(!getLangOpts().CPlusPlus && "not meant for C++ usage"); // If there is an identifier, use the location of the identifier as the // location of the decl, otherwise use the location of the struct/union // keyword. SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc; TagDecl *New = nullptr; if (Kind == TTK_Enum) { New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, nullptr, ScopedEnum, ScopedEnumUsesClassTag, !EnumUnderlying.isNull()); // If this is an undefined enum, bail. if (TUK != TUK_Definition && !Invalid) return nullptr; if (EnumUnderlying) { EnumDecl *ED = cast(New); if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast()) ED->setIntegerTypeSourceInfo(TI); else ED->setIntegerType(QualType(EnumUnderlying.get(), 0)); ED->setPromotionType(ED->getIntegerType()); } } else { // struct/union New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, nullptr); } if (RecordDecl *RD = dyn_cast(New)) { // Add alignment attributes if necessary; these attributes are checked // when the ASTContext lays out the structure. // // It is important for implementing the correct semantics that this // happen here (in ActOnTag). The #pragma pack stack is // maintained as a result of parser callbacks which can occur at // many points during the parsing of a struct declaration (because // the #pragma tokens are effectively skipped over during the // parsing of the struct). if (TUK == TUK_Definition) { AddAlignmentAttributesForRecord(RD); AddMsStructLayoutForRecord(RD); } } New->setLexicalDeclContext(CurContext); return New; }; LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl); if (Name && SS.isNotEmpty()) { // We have a nested-name tag ('struct foo::bar'). // Check for invalid 'foo::'. if (SS.isInvalid()) { Name = nullptr; goto CreateNewDecl; } // If this is a friend or a reference to a class in a dependent // context, don't try to make a decl for it. if (TUK == TUK_Friend || TUK == TUK_Reference) { DC = computeDeclContext(SS, false); if (!DC) { IsDependent = true; return nullptr; } } else { DC = computeDeclContext(SS, true); if (!DC) { Diag(SS.getRange().getBegin(), diag::err_dependent_nested_name_spec) << SS.getRange(); return nullptr; } } if (RequireCompleteDeclContext(SS, DC)) return nullptr; SearchDC = DC; // Look-up name inside 'foo::'. LookupQualifiedName(Previous, DC); if (Previous.isAmbiguous()) return nullptr; if (Previous.empty()) { // Name lookup did not find anything. However, if the // nested-name-specifier refers to the current instantiation, // and that current instantiation has any dependent base // classes, we might find something at instantiation time: treat // this as a dependent elaborated-type-specifier. // But this only makes any sense for reference-like lookups. if (Previous.wasNotFoundInCurrentInstantiation() && (TUK == TUK_Reference || TUK == TUK_Friend)) { IsDependent = true; return nullptr; } // A tag 'foo::bar' must already exist. Diag(NameLoc, diag::err_not_tag_in_scope) << Kind << Name << DC << SS.getRange(); Name = nullptr; Invalid = true; goto CreateNewDecl; } } else if (Name) { // C++14 [class.mem]p14: // If T is the name of a class, then each of the following shall have a // name different from T: // -- every member of class T that is itself a type if (TUK != TUK_Reference && TUK != TUK_Friend && DiagnoseClassNameShadow(SearchDC, DeclarationNameInfo(Name, NameLoc))) return nullptr; // If this is a named struct, check to see if there was a previous forward // declaration or definition. // FIXME: We're looking into outer scopes here, even when we // shouldn't be. Doing so can result in ambiguities that we // shouldn't be diagnosing. LookupName(Previous, S); // When declaring or defining a tag, ignore ambiguities introduced // by types using'ed into this scope. if (Previous.isAmbiguous() && (TUK == TUK_Definition || TUK == TUK_Declaration)) { LookupResult::Filter F = Previous.makeFilter(); while (F.hasNext()) { NamedDecl *ND = F.next(); if (!ND->getDeclContext()->getRedeclContext()->Equals( SearchDC->getRedeclContext())) F.erase(); } F.done(); } // C++11 [namespace.memdef]p3: // If the name in a friend declaration is neither qualified nor // a template-id and the declaration is a function or an // elaborated-type-specifier, the lookup to determine whether // the entity has been previously declared shall not consider // any scopes outside the innermost enclosing namespace. // // MSVC doesn't implement the above rule for types, so a friend tag // declaration may be a redeclaration of a type declared in an enclosing // scope. They do implement this rule for friend functions. // // Does it matter that this should be by scope instead of by // semantic context? if (!Previous.empty() && TUK == TUK_Friend) { DeclContext *EnclosingNS = SearchDC->getEnclosingNamespaceContext(); LookupResult::Filter F = Previous.makeFilter(); bool FriendSawTagOutsideEnclosingNamespace = false; while (F.hasNext()) { NamedDecl *ND = F.next(); DeclContext *DC = ND->getDeclContext()->getRedeclContext(); if (DC->isFileContext() && !EnclosingNS->Encloses(ND->getDeclContext())) { if (getLangOpts().MSVCCompat) FriendSawTagOutsideEnclosingNamespace = true; else F.erase(); } } F.done(); // Diagnose this MSVC extension in the easy case where lookup would have // unambiguously found something outside the enclosing namespace. if (Previous.isSingleResult() && FriendSawTagOutsideEnclosingNamespace) { NamedDecl *ND = Previous.getFoundDecl(); Diag(NameLoc, diag::ext_friend_tag_redecl_outside_namespace) << createFriendTagNNSFixIt(*this, ND, S, NameLoc); } } // Note: there used to be some attempt at recovery here. if (Previous.isAmbiguous()) return nullptr; if (!getLangOpts().CPlusPlus && TUK != TUK_Reference) { // FIXME: This makes sure that we ignore the contexts associated // with C structs, unions, and enums when looking for a matching // tag declaration or definition. See the similar lookup tweak // in Sema::LookupName; is there a better way to deal with this? while (isa(SearchDC) || isa(SearchDC)) SearchDC = SearchDC->getParent(); } } if (Previous.isSingleResult() && Previous.getFoundDecl()->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(NameLoc, Previous.getFoundDecl()); // Just pretend that we didn't see the previous declaration. Previous.clear(); } if (getLangOpts().CPlusPlus && Name && DC && StdNamespace && DC->Equals(getStdNamespace())) { if (Name->isStr("bad_alloc")) { // This is a declaration of or a reference to "std::bad_alloc". isStdBadAlloc = true; // If std::bad_alloc has been implicitly declared (but made invisible to // name lookup), fill in this implicit declaration as the previous // declaration, so that the declarations get chained appropriately. if (Previous.empty() && StdBadAlloc) Previous.addDecl(getStdBadAlloc()); } else if (Name->isStr("align_val_t")) { isStdAlignValT = true; if (Previous.empty() && StdAlignValT) Previous.addDecl(getStdAlignValT()); } } // If we didn't find a previous declaration, and this is a reference // (or friend reference), move to the correct scope. In C++, we // also need to do a redeclaration lookup there, just in case // there's a shadow friend decl. if (Name && Previous.empty() && (TUK == TUK_Reference || TUK == TUK_Friend || IsTemplateParamOrArg)) { if (Invalid) goto CreateNewDecl; assert(SS.isEmpty()); if (TUK == TUK_Reference || IsTemplateParamOrArg) { // C++ [basic.scope.pdecl]p5: // -- for an elaborated-type-specifier of the form // // class-key identifier // // if the elaborated-type-specifier is used in the // decl-specifier-seq or parameter-declaration-clause of a // function defined in namespace scope, the identifier is // declared as a class-name in the namespace that contains // the declaration; otherwise, except as a friend // declaration, the identifier is declared in the smallest // non-class, non-function-prototype scope that contains the // declaration. // // C99 6.7.2.3p8 has a similar (but not identical!) provision for // C structs and unions. // // It is an error in C++ to declare (rather than define) an enum // type, including via an elaborated type specifier. We'll // diagnose that later; for now, declare the enum in the same // scope as we would have picked for any other tag type. // // GNU C also supports this behavior as part of its incomplete // enum types extension, while GNU C++ does not. // // Find the context where we'll be declaring the tag. // FIXME: We would like to maintain the current DeclContext as the // lexical context, SearchDC = getTagInjectionContext(SearchDC); // Find the scope where we'll be declaring the tag. S = getTagInjectionScope(S, getLangOpts()); } else { assert(TUK == TUK_Friend); // C++ [namespace.memdef]p3: // If a friend declaration in a non-local class first declares a // class or function, the friend class or function is a member of // the innermost enclosing namespace. SearchDC = SearchDC->getEnclosingNamespaceContext(); } // In C++, we need to do a redeclaration lookup to properly // diagnose some problems. // FIXME: redeclaration lookup is also used (with and without C++) to find a // hidden declaration so that we don't get ambiguity errors when using a // type declared by an elaborated-type-specifier. In C that is not correct // and we should instead merge compatible types found by lookup. if (getLangOpts().CPlusPlus) { Previous.setRedeclarationKind(ForRedeclaration); LookupQualifiedName(Previous, SearchDC); } else { Previous.setRedeclarationKind(ForRedeclaration); LookupName(Previous, S); } } // If we have a known previous declaration to use, then use it. if (Previous.empty() && SkipBody && SkipBody->Previous) Previous.addDecl(SkipBody->Previous); if (!Previous.empty()) { NamedDecl *PrevDecl = Previous.getFoundDecl(); NamedDecl *DirectPrevDecl = Previous.getRepresentativeDecl(); // It's okay to have a tag decl in the same scope as a typedef // which hides a tag decl in the same scope. Finding this // insanity with a redeclaration lookup can only actually happen // in C++. // // This is also okay for elaborated-type-specifiers, which is // technically forbidden by the current standard but which is // okay according to the likely resolution of an open issue; // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407 if (getLangOpts().CPlusPlus) { if (TypedefNameDecl *TD = dyn_cast(PrevDecl)) { if (const TagType *TT = TD->getUnderlyingType()->getAs()) { TagDecl *Tag = TT->getDecl(); if (Tag->getDeclName() == Name && Tag->getDeclContext()->getRedeclContext() ->Equals(TD->getDeclContext()->getRedeclContext())) { PrevDecl = Tag; Previous.clear(); Previous.addDecl(Tag); Previous.resolveKind(); } } } } // If this is a redeclaration of a using shadow declaration, it must // declare a tag in the same context. In MSVC mode, we allow a // redefinition if either context is within the other. if (auto *Shadow = dyn_cast(DirectPrevDecl)) { auto *OldTag = dyn_cast(PrevDecl); if (SS.isEmpty() && TUK != TUK_Reference && TUK != TUK_Friend && isDeclInScope(Shadow, SearchDC, S, isMemberSpecialization) && !(OldTag && isAcceptableTagRedeclContext( *this, OldTag->getDeclContext(), SearchDC))) { Diag(KWLoc, diag::err_using_decl_conflict_reverse); Diag(Shadow->getTargetDecl()->getLocation(), diag::note_using_decl_target); Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) << 0; // Recover by ignoring the old declaration. Previous.clear(); goto CreateNewDecl; } } if (TagDecl *PrevTagDecl = dyn_cast(PrevDecl)) { // If this is a use of a previous tag, or if the tag is already declared // in the same scope (so that the definition/declaration completes or // rementions the tag), reuse the decl. if (TUK == TUK_Reference || TUK == TUK_Friend || isDeclInScope(DirectPrevDecl, SearchDC, S, SS.isNotEmpty() || isMemberSpecialization)) { // Make sure that this wasn't declared as an enum and now used as a // struct or something similar. if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind, TUK == TUK_Definition, KWLoc, Name)) { bool SafeToContinue = (PrevTagDecl->getTagKind() != TTK_Enum && Kind != TTK_Enum); if (SafeToContinue) Diag(KWLoc, diag::err_use_with_wrong_tag) << Name << FixItHint::CreateReplacement(SourceRange(KWLoc), PrevTagDecl->getKindName()); else Diag(KWLoc, diag::err_use_with_wrong_tag) << Name; Diag(PrevTagDecl->getLocation(), diag::note_previous_use); if (SafeToContinue) Kind = PrevTagDecl->getTagKind(); else { // Recover by making this an anonymous redefinition. Name = nullptr; Previous.clear(); Invalid = true; } } if (Kind == TTK_Enum && PrevTagDecl->getTagKind() == TTK_Enum) { const EnumDecl *PrevEnum = cast(PrevTagDecl); // If this is an elaborated-type-specifier for a scoped enumeration, // the 'class' keyword is not necessary and not permitted. if (TUK == TUK_Reference || TUK == TUK_Friend) { if (ScopedEnum) Diag(ScopedEnumKWLoc, diag::err_enum_class_reference) << PrevEnum->isScoped() << FixItHint::CreateRemoval(ScopedEnumKWLoc); return PrevTagDecl; } QualType EnumUnderlyingTy; if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast()) EnumUnderlyingTy = TI->getType().getUnqualifiedType(); else if (const Type *T = EnumUnderlying.dyn_cast()) EnumUnderlyingTy = QualType(T, 0); // All conflicts with previous declarations are recovered by // returning the previous declaration, unless this is a definition, // in which case we want the caller to bail out. if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc, ScopedEnum, EnumUnderlyingTy, EnumUnderlyingIsImplicit, PrevEnum)) return TUK == TUK_Declaration ? PrevTagDecl : nullptr; } // C++11 [class.mem]p1: // A member shall not be declared twice in the member-specification, // except that a nested class or member class template can be declared // and then later defined. if (TUK == TUK_Declaration && PrevDecl->isCXXClassMember() && S->isDeclScope(PrevDecl)) { Diag(NameLoc, diag::ext_member_redeclared); Diag(PrevTagDecl->getLocation(), diag::note_previous_declaration); } if (!Invalid) { // If this is a use, just return the declaration we found, unless // we have attributes. if (TUK == TUK_Reference || TUK == TUK_Friend) { if (Attr) { // FIXME: Diagnose these attributes. For now, we create a new // declaration to hold them. } else if (TUK == TUK_Reference && (PrevTagDecl->getFriendObjectKind() == Decl::FOK_Undeclared || PrevDecl->getOwningModule() != getCurrentModule()) && SS.isEmpty()) { // This declaration is a reference to an existing entity, but // has different visibility from that entity: it either makes // a friend visible or it makes a type visible in a new module. // In either case, create a new declaration. We only do this if // the declaration would have meant the same thing if no prior // declaration were found, that is, if it was found in the same // scope where we would have injected a declaration. if (!getTagInjectionContext(CurContext)->getRedeclContext() ->Equals(PrevDecl->getDeclContext()->getRedeclContext())) return PrevTagDecl; // This is in the injected scope, create a new declaration in // that scope. S = getTagInjectionScope(S, getLangOpts()); } else { return PrevTagDecl; } } // Diagnose attempts to redefine a tag. if (TUK == TUK_Definition) { if (NamedDecl *Def = PrevTagDecl->getDefinition()) { // If we're defining a specialization and the previous definition // is from an implicit instantiation, don't emit an error // here; we'll catch this in the general case below. bool IsExplicitSpecializationAfterInstantiation = false; if (isMemberSpecialization) { if (CXXRecordDecl *RD = dyn_cast(Def)) IsExplicitSpecializationAfterInstantiation = RD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization; else if (EnumDecl *ED = dyn_cast(Def)) IsExplicitSpecializationAfterInstantiation = ED->getTemplateSpecializationKind() != TSK_ExplicitSpecialization; } // Note that clang allows ODR-like semantics for ObjC/C, i.e., do // not keep more that one definition around (merge them). However, // ensure the decl passes the structural compatibility check in // C11 6.2.7/1 (or 6.1.2.6/1 in C89). NamedDecl *Hidden = nullptr; if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) { // There is a definition of this tag, but it is not visible. We // explicitly make use of C++'s one definition rule here, and // assume that this definition is identical to the hidden one // we already have. Make the existing definition visible and // use it in place of this one. if (!getLangOpts().CPlusPlus) { // Postpone making the old definition visible until after we // complete parsing the new one and do the structural // comparison. SkipBody->CheckSameAsPrevious = true; SkipBody->New = createTagFromNewDecl(); SkipBody->Previous = Hidden; } else { SkipBody->ShouldSkip = true; makeMergedDefinitionVisible(Hidden); } return Def; } else if (!IsExplicitSpecializationAfterInstantiation) { // A redeclaration in function prototype scope in C isn't // visible elsewhere, so merely issue a warning. if (!getLangOpts().CPlusPlus && S->containedInPrototypeScope()) Diag(NameLoc, diag::warn_redefinition_in_param_list) << Name; else Diag(NameLoc, diag::err_redefinition) << Name; notePreviousDefinition(Def, NameLoc.isValid() ? NameLoc : KWLoc); // If this is a redefinition, recover by making this // struct be anonymous, which will make any later // references get the previous definition. Name = nullptr; Previous.clear(); Invalid = true; } } else { // If the type is currently being defined, complain // about a nested redefinition. auto *TD = Context.getTagDeclType(PrevTagDecl)->getAsTagDecl(); if (TD->isBeingDefined()) { Diag(NameLoc, diag::err_nested_redefinition) << Name; Diag(PrevTagDecl->getLocation(), diag::note_previous_definition); Name = nullptr; Previous.clear(); Invalid = true; } } // Okay, this is definition of a previously declared or referenced // tag. We're going to create a new Decl for it. } // Okay, we're going to make a redeclaration. If this is some kind // of reference, make sure we build the redeclaration in the same DC // as the original, and ignore the current access specifier. if (TUK == TUK_Friend || TUK == TUK_Reference) { SearchDC = PrevTagDecl->getDeclContext(); AS = AS_none; } } // If we get here we have (another) forward declaration or we // have a definition. Just create a new decl. } else { // If we get here, this is a definition of a new tag type in a nested // scope, e.g. "struct foo; void bar() { struct foo; }", just create a // new decl/type. We set PrevDecl to NULL so that the entities // have distinct types. Previous.clear(); } // If we get here, we're going to create a new Decl. If PrevDecl // is non-NULL, it's a definition of the tag declared by // PrevDecl. If it's NULL, we have a new definition. // Otherwise, PrevDecl is not a tag, but was found with tag // lookup. This is only actually possible in C++, where a few // things like templates still live in the tag namespace. } else { // Use a better diagnostic if an elaborated-type-specifier // found the wrong kind of type on the first // (non-redeclaration) lookup. if ((TUK == TUK_Reference || TUK == TUK_Friend) && !Previous.isForRedeclaration()) { NonTagKind NTK = getNonTagTypeDeclKind(PrevDecl, Kind); Diag(NameLoc, diag::err_tag_reference_non_tag) << PrevDecl << NTK << Kind; Diag(PrevDecl->getLocation(), diag::note_declared_at); Invalid = true; // Otherwise, only diagnose if the declaration is in scope. } else if (!isDeclInScope(DirectPrevDecl, SearchDC, S, SS.isNotEmpty() || isMemberSpecialization)) { // do nothing // Diagnose implicit declarations introduced by elaborated types. } else if (TUK == TUK_Reference || TUK == TUK_Friend) { NonTagKind NTK = getNonTagTypeDeclKind(PrevDecl, Kind); Diag(NameLoc, diag::err_tag_reference_conflict) << NTK; Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; Invalid = true; // Otherwise it's a declaration. Call out a particularly common // case here. } else if (TypedefNameDecl *TND = dyn_cast(PrevDecl)) { unsigned Kind = 0; if (isa(PrevDecl)) Kind = 1; Diag(NameLoc, diag::err_tag_definition_of_typedef) << Name << Kind << TND->getUnderlyingType(); Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; Invalid = true; // Otherwise, diagnose. } else { // The tag name clashes with something else in the target scope, // issue an error and recover by making this tag be anonymous. Diag(NameLoc, diag::err_redefinition_different_kind) << Name; notePreviousDefinition(PrevDecl, NameLoc); Name = nullptr; Invalid = true; } // The existing declaration isn't relevant to us; we're in a // new scope, so clear out the previous declaration. Previous.clear(); } } CreateNewDecl: TagDecl *PrevDecl = nullptr; if (Previous.isSingleResult()) PrevDecl = cast(Previous.getFoundDecl()); // If there is an identifier, use the location of the identifier as the // location of the decl, otherwise use the location of the struct/union // keyword. SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc; // Otherwise, create a new declaration. If there is a previous // declaration of the same entity, the two will be linked via // PrevDecl. TagDecl *New; bool IsForwardReference = false; if (Kind == TTK_Enum) { // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: // enum X { A, B, C } D; D should chain to X. New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, cast_or_null(PrevDecl), ScopedEnum, ScopedEnumUsesClassTag, !EnumUnderlying.isNull()); if (isStdAlignValT && (!StdAlignValT || getStdAlignValT()->isImplicit())) StdAlignValT = cast(New); // If this is an undefined enum, warn. if (TUK != TUK_Definition && !Invalid) { TagDecl *Def; if (!EnumUnderlyingIsImplicit && (getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) && cast(New)->isFixed()) { // C++0x: 7.2p2: opaque-enum-declaration. // Conflicts are diagnosed above. Do nothing. } else if (PrevDecl && (Def = cast(PrevDecl)->getDefinition())) { Diag(Loc, diag::ext_forward_ref_enum_def) << New; Diag(Def->getLocation(), diag::note_previous_definition); } else { unsigned DiagID = diag::ext_forward_ref_enum; if (getLangOpts().MSVCCompat) DiagID = diag::ext_ms_forward_ref_enum; else if (getLangOpts().CPlusPlus) DiagID = diag::err_forward_ref_enum; Diag(Loc, DiagID); // If this is a forward-declared reference to an enumeration, make a // note of it; we won't actually be introducing the declaration into // the declaration context. if (TUK == TUK_Reference) IsForwardReference = true; } } if (EnumUnderlying) { EnumDecl *ED = cast(New); if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast()) ED->setIntegerTypeSourceInfo(TI); else ED->setIntegerType(QualType(EnumUnderlying.get(), 0)); ED->setPromotionType(ED->getIntegerType()); } } else { // struct/union/class // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: // struct X { int A; } D; D should chain to X. if (getLangOpts().CPlusPlus) { // FIXME: Look for a way to use RecordDecl for simple structs. New = CXXRecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, cast_or_null(PrevDecl)); if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit())) StdBadAlloc = cast(New); } else New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, cast_or_null(PrevDecl)); } // C++11 [dcl.type]p3: // A type-specifier-seq shall not define a class or enumeration [...]. if (getLangOpts().CPlusPlus && (IsTypeSpecifier || IsTemplateParamOrArg) && TUK == TUK_Definition) { Diag(New->getLocation(), diag::err_type_defined_in_type_specifier) << Context.getTagDeclType(New); Invalid = true; } // Maybe add qualifier info. if (SS.isNotEmpty()) { if (SS.isSet()) { // If this is either a declaration or a definition, check the // nested-name-specifier against the current context. We don't do this // for explicit specializations, because they have similar checking // (with more specific diagnostics) in the call to // CheckMemberSpecialization, below. if (!isMemberSpecialization && (TUK == TUK_Definition || TUK == TUK_Declaration) && diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc)) Invalid = true; New->setQualifierInfo(SS.getWithLocInContext(Context)); if (TemplateParameterLists.size() > 0) { New->setTemplateParameterListsInfo(Context, TemplateParameterLists); } } else Invalid = true; } if (RecordDecl *RD = dyn_cast(New)) { // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. // // It is important for implementing the correct semantics that this // happen here (in ActOnTag). The #pragma pack stack is // maintained as a result of parser callbacks which can occur at // many points during the parsing of a struct declaration (because // the #pragma tokens are effectively skipped over during the // parsing of the struct). if (TUK == TUK_Definition) { AddAlignmentAttributesForRecord(RD); AddMsStructLayoutForRecord(RD); } } if (ModulePrivateLoc.isValid()) { if (isMemberSpecialization) Diag(New->getLocation(), diag::err_module_private_specialization) << 2 << FixItHint::CreateRemoval(ModulePrivateLoc); // __module_private__ does not apply to local classes. However, we only // diagnose this as an error when the declaration specifiers are // freestanding. Here, we just ignore the __module_private__. else if (!SearchDC->isFunctionOrMethod()) New->setModulePrivate(); } // If this is a specialization of a member class (of a class template), // check the specialization. if (isMemberSpecialization && CheckMemberSpecialization(New, Previous)) Invalid = true; // If we're declaring or defining a tag in function prototype scope in C, // note that this type can only be used within the function and add it to // the list of decls to inject into the function definition scope. if ((Name || Kind == TTK_Enum) && getNonFieldDeclScope(S)->isFunctionPrototypeScope()) { if (getLangOpts().CPlusPlus) { // C++ [dcl.fct]p6: // Types shall not be defined in return or parameter types. if (TUK == TUK_Definition && !IsTypeSpecifier) { Diag(Loc, diag::err_type_defined_in_param_type) << Name; Invalid = true; } } else if (!PrevDecl) { Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New); } } if (Invalid) New->setInvalidDecl(); // Set the lexical context. If the tag has a C++ scope specifier, the // lexical context will be different from the semantic context. New->setLexicalDeclContext(CurContext); // Mark this as a friend decl if applicable. // In Microsoft mode, a friend declaration also acts as a forward // declaration so we always pass true to setObjectOfFriendDecl to make // the tag name visible. if (TUK == TUK_Friend) New->setObjectOfFriendDecl(getLangOpts().MSVCCompat); // Set the access specifier. if (!Invalid && SearchDC->isRecord()) SetMemberAccessSpecifier(New, PrevDecl, AS); if (TUK == TUK_Definition) New->startDefinition(); if (Attr) ProcessDeclAttributeList(S, New, Attr); AddPragmaAttributes(S, New); // If this has an identifier, add it to the scope stack. if (TUK == TUK_Friend) { // We might be replacing an existing declaration in the lookup tables; // if so, borrow its access specifier. if (PrevDecl) New->setAccess(PrevDecl->getAccess()); DeclContext *DC = New->getDeclContext()->getRedeclContext(); DC->makeDeclVisibleInContext(New); if (Name) // can be null along some error paths if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false); } else if (Name) { S = getNonFieldDeclScope(S); PushOnScopeChains(New, S, !IsForwardReference); if (IsForwardReference) SearchDC->makeDeclVisibleInContext(New); } else { CurContext->addDecl(New); } // If this is the C FILE type, notify the AST context. if (IdentifierInfo *II = New->getIdentifier()) if (!New->isInvalidDecl() && New->getDeclContext()->getRedeclContext()->isTranslationUnit() && II->isStr("FILE")) Context.setFILEDecl(New); if (PrevDecl) mergeDeclAttributes(New, PrevDecl); // If there's a #pragma GCC visibility in scope, set the visibility of this // record. AddPushedVisibilityAttribute(New); if (isMemberSpecialization && !New->isInvalidDecl()) CompleteMemberSpecialization(New, Previous); OwnedDecl = true; // In C++, don't return an invalid declaration. We can't recover well from // the cases where we make the type anonymous. if (Invalid && getLangOpts().CPlusPlus) { if (New->isBeingDefined()) if (auto RD = dyn_cast(New)) RD->completeDefinition(); return nullptr; } else { return New; } } void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) { AdjustDeclIfTemplate(TagD); TagDecl *Tag = cast(TagD); // Enter the tag context. PushDeclContext(S, Tag); ActOnDocumentableDecl(TagD); // If there's a #pragma GCC visibility in scope, set the visibility of this // record. AddPushedVisibilityAttribute(Tag); } bool Sema::ActOnDuplicateDefinition(DeclSpec &DS, Decl *Prev, SkipBodyInfo &SkipBody) { if (!hasStructuralCompatLayout(Prev, SkipBody.New)) return false; // Make the previous decl visible. makeMergedDefinitionVisible(SkipBody.Previous); return true; } Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) { assert(isa(IDecl) && "ActOnObjCContainerStartDefinition - Not ObjCContainerDecl"); DeclContext *OCD = cast(IDecl); assert(getContainingDC(OCD) == CurContext && "The next DeclContext should be lexically contained in the current one."); CurContext = OCD; return IDecl; } void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, SourceLocation FinalLoc, bool IsFinalSpelledSealed, SourceLocation LBraceLoc) { AdjustDeclIfTemplate(TagD); CXXRecordDecl *Record = cast(TagD); FieldCollector->StartClass(); if (!Record->getIdentifier()) return; if (FinalLoc.isValid()) Record->addAttr(new (Context) FinalAttr(FinalLoc, Context, IsFinalSpelledSealed)); // C++ [class]p2: // [...] The class-name is also inserted into the scope of the // class itself; this is known as the injected-class-name. For // purposes of access checking, the injected-class-name is treated // as if it were a public member name. CXXRecordDecl *InjectedClassName = CXXRecordDecl::Create(Context, Record->getTagKind(), CurContext, Record->getLocStart(), Record->getLocation(), Record->getIdentifier(), /*PrevDecl=*/nullptr, /*DelayTypeCreation=*/true); Context.getTypeDeclType(InjectedClassName, Record); InjectedClassName->setImplicit(); InjectedClassName->setAccess(AS_public); if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) InjectedClassName->setDescribedClassTemplate(Template); PushOnScopeChains(InjectedClassName, S); assert(InjectedClassName->isInjectedClassName() && "Broken injected-class-name"); } void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, SourceRange BraceRange) { AdjustDeclIfTemplate(TagD); TagDecl *Tag = cast(TagD); Tag->setBraceRange(BraceRange); // Make sure we "complete" the definition even it is invalid. if (Tag->isBeingDefined()) { assert(Tag->isInvalidDecl() && "We should already have completed it"); if (RecordDecl *RD = dyn_cast(Tag)) RD->completeDefinition(); } if (isa(Tag)) { FieldCollector->FinishClass(); } // Exit this scope of this tag's definition. PopDeclContext(); if (getCurLexicalContext()->isObjCContainer() && Tag->getDeclContext()->isFileContext()) Tag->setTopLevelDeclInObjCContainer(); // Notify the consumer that we've defined a tag. if (!Tag->isInvalidDecl()) Consumer.HandleTagDeclDefinition(Tag); } void Sema::ActOnObjCContainerFinishDefinition() { // Exit this scope of this interface definition. PopDeclContext(); } void Sema::ActOnObjCTemporaryExitContainerContext(DeclContext *DC) { assert(DC == CurContext && "Mismatch of container contexts"); OriginalLexicalContext = DC; ActOnObjCContainerFinishDefinition(); } void Sema::ActOnObjCReenterContainerContext(DeclContext *DC) { ActOnObjCContainerStartDefinition(cast(DC)); OriginalLexicalContext = nullptr; } void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) { AdjustDeclIfTemplate(TagD); TagDecl *Tag = cast(TagD); Tag->setInvalidDecl(); // Make sure we "complete" the definition even it is invalid. if (Tag->isBeingDefined()) { if (RecordDecl *RD = dyn_cast(Tag)) RD->completeDefinition(); } // We're undoing ActOnTagStartDefinition here, not // ActOnStartCXXMemberDeclarations, so we don't have to mess with // the FieldCollector. PopDeclContext(); } // Note that FieldName may be null for anonymous bitfields. ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, QualType FieldTy, bool IsMsStruct, Expr *BitWidth, bool *ZeroWidth) { // Default to true; that shouldn't confuse checks for emptiness if (ZeroWidth) *ZeroWidth = true; // C99 6.7.2.1p4 - verify the field type. // C++ 9.6p3: A bit-field shall have integral or enumeration type. if (!FieldTy->isDependentType() && !FieldTy->isIntegralOrEnumerationType()) { // Handle incomplete types with specific error. if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete)) return ExprError(); if (FieldName) return Diag(FieldLoc, diag::err_not_integral_type_bitfield) << FieldName << FieldTy << BitWidth->getSourceRange(); return Diag(FieldLoc, diag::err_not_integral_type_anon_bitfield) << FieldTy << BitWidth->getSourceRange(); } else if (DiagnoseUnexpandedParameterPack(const_cast(BitWidth), UPPC_BitFieldWidth)) return ExprError(); // If the bit-width is type- or value-dependent, don't try to check // it now. if (BitWidth->isValueDependent() || BitWidth->isTypeDependent()) return BitWidth; llvm::APSInt Value; ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Value); if (ICE.isInvalid()) return ICE; BitWidth = ICE.get(); if (Value != 0 && ZeroWidth) *ZeroWidth = false; // Zero-width bitfield is ok for anonymous field. if (Value == 0 && FieldName) return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName; if (Value.isSigned() && Value.isNegative()) { if (FieldName) return Diag(FieldLoc, diag::err_bitfield_has_negative_width) << FieldName << Value.toString(10); return Diag(FieldLoc, diag::err_anon_bitfield_has_negative_width) << Value.toString(10); } if (!FieldTy->isDependentType()) { uint64_t TypeStorageSize = Context.getTypeSize(FieldTy); uint64_t TypeWidth = Context.getIntWidth(FieldTy); bool BitfieldIsOverwide = Value.ugt(TypeWidth); // Over-wide bitfields are an error in C or when using the MSVC bitfield // ABI. bool CStdConstraintViolation = BitfieldIsOverwide && !getLangOpts().CPlusPlus; bool MSBitfieldViolation = Value.ugt(TypeStorageSize) && (IsMsStruct || Context.getTargetInfo().getCXXABI().isMicrosoft()); if (CStdConstraintViolation || MSBitfieldViolation) { unsigned DiagWidth = CStdConstraintViolation ? TypeWidth : TypeStorageSize; if (FieldName) return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_width) << FieldName << (unsigned)Value.getZExtValue() << !CStdConstraintViolation << DiagWidth; return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_width) << (unsigned)Value.getZExtValue() << !CStdConstraintViolation << DiagWidth; } // Warn on types where the user might conceivably expect to get all // specified bits as value bits: that's all integral types other than // 'bool'. if (BitfieldIsOverwide && !FieldTy->isBooleanType()) { if (FieldName) Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_width) << FieldName << (unsigned)Value.getZExtValue() << (unsigned)TypeWidth; else Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_width) << (unsigned)Value.getZExtValue() << (unsigned)TypeWidth; } } return BitWidth; } /// ActOnField - Each field of a C struct/union is passed into this in order /// to create a FieldDecl object for it. Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth) { FieldDecl *Res = HandleField(S, cast_or_null(TagD), DeclStart, D, static_cast(BitfieldWidth), /*InitStyle=*/ICIS_NoInit, AS_public); return Res; } /// HandleField - Analyze a field of a C struct or a C++ data member. /// FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, SourceLocation DeclStart, Declarator &D, Expr *BitWidth, InClassInitStyle InitStyle, AccessSpecifier AS) { if (D.isDecompositionDeclarator()) { const DecompositionDeclarator &Decomp = D.getDecompositionDeclarator(); Diag(Decomp.getLSquareLoc(), diag::err_decomp_decl_context) << Decomp.getSourceRange(); return nullptr; } IdentifierInfo *II = D.getIdentifier(); SourceLocation Loc = DeclStart; if (II) Loc = D.getIdentifierLoc(); TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType T = TInfo->getType(); if (getLangOpts().CPlusPlus) { CheckExtraCXXDefaultArguments(D); if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, UPPC_DataMemberType)) { D.setInvalidType(); T = Context.IntTy; TInfo = Context.getTrivialTypeSourceInfo(T, Loc); } } // TR 18037 does not allow fields to be declared with address spaces. if (T.getQualifiers().hasAddressSpace()) { Diag(Loc, diag::err_field_with_address_space); D.setInvalidType(); } // OpenCL v1.2 s6.9b,r & OpenCL v2.0 s6.12.5 - The following types cannot be // used as structure or union field: image, sampler, event or block types. if (LangOpts.OpenCL && (T->isEventT() || T->isImageType() || T->isSamplerT() || T->isBlockPointerType())) { Diag(Loc, diag::err_opencl_type_struct_or_union_field) << T; D.setInvalidType(); } DiagnoseFunctionSpecifiers(D.getDeclSpec()); if (D.getDeclSpec().isInlineSpecified()) Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function) << getLangOpts().CPlusPlus1z; if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), diag::err_invalid_thread) << DeclSpec::getSpecifierName(TSCS); // Check to see if this name was declared as a member previously NamedDecl *PrevDecl = nullptr; LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration); LookupName(Previous, S); switch (Previous.getResultKind()) { case LookupResult::Found: case LookupResult::FoundUnresolvedValue: PrevDecl = Previous.getAsSingle(); break; case LookupResult::FoundOverloaded: PrevDecl = Previous.getRepresentativeDecl(); break; case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: case LookupResult::Ambiguous: break; } Previous.suppressDiagnostics(); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); // Just pretend that we didn't see the previous declaration. PrevDecl = nullptr; } if (PrevDecl && !isDeclInScope(PrevDecl, Record, S)) PrevDecl = nullptr; bool Mutable = (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable); SourceLocation TSSL = D.getLocStart(); FieldDecl *NewFD = CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, InitStyle, TSSL, AS, PrevDecl, &D); if (NewFD->isInvalidDecl()) Record->setInvalidDecl(); if (D.getDeclSpec().isModulePrivateSpecified()) NewFD->setModulePrivate(); if (NewFD->isInvalidDecl() && PrevDecl) { // Don't introduce NewFD into scope; there's already something // with the same name in the same scope. } else if (II) { PushOnScopeChains(NewFD, S); } else Record->addDecl(NewFD); return NewFD; } /// \brief Build a new FieldDecl and check its well-formedness. /// /// This routine builds a new FieldDecl given the fields name, type, /// record, etc. \p PrevDecl should refer to any previous declaration /// with the same name and in the same scope as the field to be /// created. /// /// \returns a new FieldDecl. /// /// \todo The Declarator argument is a hack. It will be removed once FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, TypeSourceInfo *TInfo, RecordDecl *Record, SourceLocation Loc, bool Mutable, Expr *BitWidth, InClassInitStyle InitStyle, SourceLocation TSSL, AccessSpecifier AS, NamedDecl *PrevDecl, Declarator *D) { IdentifierInfo *II = Name.getAsIdentifierInfo(); bool InvalidDecl = false; if (D) InvalidDecl = D->isInvalidType(); // If we receive a broken type, recover by assuming 'int' and // marking this declaration as invalid. if (T.isNull()) { InvalidDecl = true; T = Context.IntTy; } QualType EltTy = Context.getBaseElementType(T); if (!EltTy->isDependentType()) { if (RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) { // Fields of incomplete type force their record to be invalid. Record->setInvalidDecl(); InvalidDecl = true; } else { NamedDecl *Def; EltTy->isIncompleteType(&Def); if (Def && Def->isInvalidDecl()) { Record->setInvalidDecl(); InvalidDecl = true; } } } // OpenCL v1.2 s6.9.c: bitfields are not supported. if (BitWidth && getLangOpts().OpenCL) { Diag(Loc, diag::err_opencl_bitfields); InvalidDecl = true; } // C99 6.7.2.1p8: A member of a structure or union may have any type other // than a variably modified type. if (!InvalidDecl && T->isVariablyModifiedType()) { bool SizeIsNegative; llvm::APSInt Oversized; TypeSourceInfo *FixedTInfo = TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context, SizeIsNegative, Oversized); if (FixedTInfo) { Diag(Loc, diag::warn_illegal_constant_array_size); TInfo = FixedTInfo; T = FixedTInfo->getType(); } else { if (SizeIsNegative) Diag(Loc, diag::err_typecheck_negative_array_size); else if (Oversized.getBoolValue()) Diag(Loc, diag::err_array_too_large) << Oversized.toString(10); else Diag(Loc, diag::err_typecheck_field_variable_size); InvalidDecl = true; } } // Fields can not have abstract class types if (!InvalidDecl && RequireNonAbstractType(Loc, T, diag::err_abstract_type_in_decl, AbstractFieldType)) InvalidDecl = true; bool ZeroWidth = false; if (InvalidDecl) BitWidth = nullptr; // If this is declared as a bit-field, check the bit-field. if (BitWidth) { BitWidth = VerifyBitField(Loc, II, T, Record->isMsStruct(Context), BitWidth, &ZeroWidth).get(); if (!BitWidth) { InvalidDecl = true; BitWidth = nullptr; ZeroWidth = false; } } // Check that 'mutable' is consistent with the type of the declaration. if (!InvalidDecl && Mutable) { unsigned DiagID = 0; if (T->isReferenceType()) DiagID = getLangOpts().MSVCCompat ? diag::ext_mutable_reference : diag::err_mutable_reference; else if (T.isConstQualified()) DiagID = diag::err_mutable_const; if (DiagID) { SourceLocation ErrLoc = Loc; if (D && D->getDeclSpec().getStorageClassSpecLoc().isValid()) ErrLoc = D->getDeclSpec().getStorageClassSpecLoc(); Diag(ErrLoc, DiagID); if (DiagID != diag::ext_mutable_reference) { Mutable = false; InvalidDecl = true; } } } // C++11 [class.union]p8 (DR1460): // At most one variant member of a union may have a // brace-or-equal-initializer. if (InitStyle != ICIS_NoInit) checkDuplicateDefaultInit(*this, cast(Record), Loc); FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo, BitWidth, Mutable, InitStyle); if (InvalidDecl) NewFD->setInvalidDecl(); if (PrevDecl && !isa(PrevDecl)) { Diag(Loc, diag::err_duplicate_member) << II; Diag(PrevDecl->getLocation(), diag::note_previous_declaration); NewFD->setInvalidDecl(); } if (!InvalidDecl && getLangOpts().CPlusPlus) { if (Record->isUnion()) { if (const RecordType *RT = EltTy->getAs()) { CXXRecordDecl* RDecl = cast(RT->getDecl()); if (RDecl->getDefinition()) { // C++ [class.union]p1: An object of a class with a non-trivial // constructor, a non-trivial copy constructor, a non-trivial // destructor, or a non-trivial copy assignment operator // cannot be a member of a union, nor can an array of such // objects. if (CheckNontrivialField(NewFD)) NewFD->setInvalidDecl(); } } // C++ [class.union]p1: If a union contains a member of reference type, // the program is ill-formed, except when compiling with MSVC extensions // enabled. if (EltTy->isReferenceType()) { Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ? diag::ext_union_member_of_reference_type : diag::err_union_member_of_reference_type) << NewFD->getDeclName() << EltTy; if (!getLangOpts().MicrosoftExt) NewFD->setInvalidDecl(); } } } // FIXME: We need to pass in the attributes given an AST // representation, not a parser representation. if (D) { // FIXME: The current scope is almost... but not entirely... correct here. ProcessDeclAttributes(getCurScope(), NewFD, *D); if (NewFD->hasAttrs()) CheckAlignasUnderalignment(NewFD); } // In auto-retain/release, infer strong retension for fields of // retainable type. if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewFD)) NewFD->setInvalidDecl(); if (T.isObjCGCWeak()) Diag(Loc, diag::warn_attribute_weak_on_field); NewFD->setAccess(AS); return NewFD; } bool Sema::CheckNontrivialField(FieldDecl *FD) { assert(FD); assert(getLangOpts().CPlusPlus && "valid check only for C++"); if (FD->isInvalidDecl() || FD->getType()->isDependentType()) return false; QualType EltTy = Context.getBaseElementType(FD->getType()); if (const RecordType *RT = EltTy->getAs()) { CXXRecordDecl *RDecl = cast(RT->getDecl()); if (RDecl->getDefinition()) { // We check for copy constructors before constructors // because otherwise we'll never get complaints about // copy constructors. CXXSpecialMember member = CXXInvalid; // We're required to check for any non-trivial constructors. Since the // implicit default constructor is suppressed if there are any // user-declared constructors, we just need to check that there is a // trivial default constructor and a trivial copy constructor. (We don't // worry about move constructors here, since this is a C++98 check.) if (RDecl->hasNonTrivialCopyConstructor()) member = CXXCopyConstructor; else if (!RDecl->hasTrivialDefaultConstructor()) member = CXXDefaultConstructor; else if (RDecl->hasNonTrivialCopyAssignment()) member = CXXCopyAssignment; else if (RDecl->hasNonTrivialDestructor()) member = CXXDestructor; if (member != CXXInvalid) { if (!getLangOpts().CPlusPlus11 && getLangOpts().ObjCAutoRefCount && RDecl->hasObjectMember()) { // Objective-C++ ARC: it is an error to have a non-trivial field of // a union. However, system headers in Objective-C programs // occasionally have Objective-C lifetime objects within unions, // and rather than cause the program to fail, we make those // members unavailable. SourceLocation Loc = FD->getLocation(); if (getSourceManager().isInSystemHeader(Loc)) { if (!FD->hasAttr()) FD->addAttr(UnavailableAttr::CreateImplicit(Context, "", UnavailableAttr::IR_ARCFieldWithOwnership, Loc)); return false; } } Diag(FD->getLocation(), getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member : diag::err_illegal_union_or_anon_struct_member) << FD->getParent()->isUnion() << FD->getDeclName() << member; DiagnoseNontrivial(RDecl, member); return !getLangOpts().CPlusPlus11; } } } return false; } /// TranslateIvarVisibility - Translate visibility from a token ID to an /// AST enum value. static ObjCIvarDecl::AccessControl TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) { switch (ivarVisibility) { default: llvm_unreachable("Unknown visitibility kind"); case tok::objc_private: return ObjCIvarDecl::Private; case tok::objc_public: return ObjCIvarDecl::Public; case tok::objc_protected: return ObjCIvarDecl::Protected; case tok::objc_package: return ObjCIvarDecl::Package; } } /// ActOnIvar - Each ivar field of an objective-c class is passed into this /// in order to create an IvarDecl object for it. Decl *Sema::ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth, tok::ObjCKeywordKind Visibility) { IdentifierInfo *II = D.getIdentifier(); Expr *BitWidth = (Expr*)BitfieldWidth; SourceLocation Loc = DeclStart; if (II) Loc = D.getIdentifierLoc(); // FIXME: Unnamed fields can be handled in various different ways, for // example, unnamed unions inject all members into the struct namespace! TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType T = TInfo->getType(); if (BitWidth) { // 6.7.2.1p3, 6.7.2.1p4 BitWidth = VerifyBitField(Loc, II, T, /*IsMsStruct*/false, BitWidth).get(); if (!BitWidth) D.setInvalidType(); } else { // Not a bitfield. // validate II. } if (T->isReferenceType()) { Diag(Loc, diag::err_ivar_reference_type); D.setInvalidType(); } // C99 6.7.2.1p8: A member of a structure or union may have any type other // than a variably modified type. else if (T->isVariablyModifiedType()) { Diag(Loc, diag::err_typecheck_ivar_variable_size); D.setInvalidType(); } // Get the visibility (access control) for this ivar. ObjCIvarDecl::AccessControl ac = Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility) : ObjCIvarDecl::None; // Must set ivar's DeclContext to its enclosing interface. ObjCContainerDecl *EnclosingDecl = cast(CurContext); if (!EnclosingDecl || EnclosingDecl->isInvalidDecl()) return nullptr; ObjCContainerDecl *EnclosingContext; if (ObjCImplementationDecl *IMPDecl = dyn_cast(EnclosingDecl)) { if (LangOpts.ObjCRuntime.isFragile()) { // Case of ivar declared in an implementation. Context is that of its class. EnclosingContext = IMPDecl->getClassInterface(); assert(EnclosingContext && "Implementation has no class interface!"); } else EnclosingContext = EnclosingDecl; } else { if (ObjCCategoryDecl *CDecl = dyn_cast(EnclosingDecl)) { if (LangOpts.ObjCRuntime.isFragile() || !CDecl->IsClassExtension()) { Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension(); return nullptr; } } EnclosingContext = EnclosingDecl; } // Construct the decl. ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, EnclosingContext, DeclStart, Loc, II, T, TInfo, ac, (Expr *)BitfieldWidth); if (II) { NamedDecl *PrevDecl = LookupSingleName(S, II, Loc, LookupMemberName, ForRedeclaration); if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S) && !isa(PrevDecl)) { Diag(Loc, diag::err_duplicate_member) << II; Diag(PrevDecl->getLocation(), diag::note_previous_declaration); NewID->setInvalidDecl(); } } // Process attributes attached to the ivar. ProcessDeclAttributes(S, NewID, D); if (D.isInvalidType()) NewID->setInvalidDecl(); // In ARC, infer 'retaining' for ivars of retainable type. if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewID)) NewID->setInvalidDecl(); if (D.getDeclSpec().isModulePrivateSpecified()) NewID->setModulePrivate(); if (II) { // FIXME: When interfaces are DeclContexts, we'll need to add // these to the interface. S->AddDecl(NewID); IdResolver.AddDecl(NewID); } if (LangOpts.ObjCRuntime.isNonFragile() && !NewID->isInvalidDecl() && isa(EnclosingDecl)) Diag(Loc, diag::warn_ivars_in_interface); return NewID; } /// ActOnLastBitfield - This routine handles synthesized bitfields rules for /// class and class extensions. For every class \@interface and class /// extension \@interface, if the last ivar is a bitfield of any type, /// then add an implicit `char :0` ivar to the end of that interface. void Sema::ActOnLastBitfield(SourceLocation DeclLoc, SmallVectorImpl &AllIvarDecls) { if (LangOpts.ObjCRuntime.isFragile() || AllIvarDecls.empty()) return; Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1]; ObjCIvarDecl *Ivar = cast(ivarDecl); if (!Ivar->isBitField() || Ivar->getBitWidthValue(Context) == 0) return; ObjCInterfaceDecl *ID = dyn_cast(CurContext); if (!ID) { if (ObjCCategoryDecl *CD = dyn_cast(CurContext)) { if (!CD->IsClassExtension()) return; } // No need to add this to end of @implementation. else return; } // All conditions are met. Add a new bitfield to the tail end of ivars. llvm::APInt Zero(Context.getTypeSize(Context.IntTy), 0); Expr * BW = IntegerLiteral::Create(Context, Zero, Context.IntTy, DeclLoc); Ivar = ObjCIvarDecl::Create(Context, cast(CurContext), DeclLoc, DeclLoc, nullptr, Context.CharTy, Context.getTrivialTypeSourceInfo(Context.CharTy, DeclLoc), ObjCIvarDecl::Private, BW, true); AllIvarDecls.push_back(Ivar); } void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, ArrayRef Fields, SourceLocation LBrac, SourceLocation RBrac, AttributeList *Attr) { assert(EnclosingDecl && "missing record or interface decl"); // If this is an Objective-C @implementation or category and we have // new fields here we should reset the layout of the interface since // it will now change. if (!Fields.empty() && isa(EnclosingDecl)) { ObjCContainerDecl *DC = cast(EnclosingDecl); switch (DC->getKind()) { default: break; case Decl::ObjCCategory: Context.ResetObjCLayout(cast(DC)->getClassInterface()); break; case Decl::ObjCImplementation: Context. ResetObjCLayout(cast(DC)->getClassInterface()); break; } } RecordDecl *Record = dyn_cast(EnclosingDecl); // Start counting up the number of named members; make sure to include // members of anonymous structs and unions in the total. unsigned NumNamedMembers = 0; if (Record) { for (const auto *I : Record->decls()) { if (const auto *IFD = dyn_cast(I)) if (IFD->getDeclName()) ++NumNamedMembers; } } // Verify that all the fields are okay. SmallVector RecFields; bool ObjCFieldLifetimeErrReported = false; for (ArrayRef::iterator i = Fields.begin(), end = Fields.end(); i != end; ++i) { FieldDecl *FD = cast(*i); // Get the type for the field. const Type *FDTy = FD->getType().getTypePtr(); if (!FD->isAnonymousStructOrUnion()) { // Remember all fields written by the user. RecFields.push_back(FD); } // If the field is already invalid for some reason, don't emit more // diagnostics about it. if (FD->isInvalidDecl()) { EnclosingDecl->setInvalidDecl(); continue; } // C99 6.7.2.1p2: // A structure or union shall not contain a member with // incomplete or function type (hence, a structure shall not // contain an instance of itself, but may contain a pointer to // an instance of itself), except that the last member of a // structure with more than one named member may have incomplete // array type; such a structure (and any union containing, // possibly recursively, a member that is such a structure) // shall not be a member of a structure or an element of an // array. if (FDTy->isFunctionType()) { // Field declared as a function. Diag(FD->getLocation(), diag::err_field_declared_as_function) << FD->getDeclName(); FD->setInvalidDecl(); EnclosingDecl->setInvalidDecl(); continue; } else if (FDTy->isIncompleteArrayType() && Record && ((i + 1 == Fields.end() && !Record->isUnion()) || ((getLangOpts().MicrosoftExt || getLangOpts().CPlusPlus) && (i + 1 == Fields.end() || Record->isUnion())))) { // Flexible array member. // Microsoft and g++ is more permissive regarding flexible array. // It will accept flexible array in union and also // as the sole element of a struct/class. unsigned DiagID = 0; if (Record->isUnion()) DiagID = getLangOpts().MicrosoftExt ? diag::ext_flexible_array_union_ms : getLangOpts().CPlusPlus ? diag::ext_flexible_array_union_gnu : diag::err_flexible_array_union; else if (NumNamedMembers < 1) DiagID = getLangOpts().MicrosoftExt ? diag::ext_flexible_array_empty_aggregate_ms : getLangOpts().CPlusPlus ? diag::ext_flexible_array_empty_aggregate_gnu : diag::err_flexible_array_empty_aggregate; if (DiagID) Diag(FD->getLocation(), DiagID) << FD->getDeclName() << Record->getTagKind(); // While the layout of types that contain virtual bases is not specified // by the C++ standard, both the Itanium and Microsoft C++ ABIs place // virtual bases after the derived members. This would make a flexible // array member declared at the end of an object not adjacent to the end // of the type. if (CXXRecordDecl *RD = dyn_cast(Record)) if (RD->getNumVBases() != 0) Diag(FD->getLocation(), diag::err_flexible_array_virtual_base) << FD->getDeclName() << Record->getTagKind(); if (!getLangOpts().C99) Diag(FD->getLocation(), diag::ext_c99_flexible_array_member) << FD->getDeclName() << Record->getTagKind(); // If the element type has a non-trivial destructor, we would not // implicitly destroy the elements, so disallow it for now. // // FIXME: GCC allows this. We should probably either implicitly delete // the destructor of the containing class, or just allow this. QualType BaseElem = Context.getBaseElementType(FD->getType()); if (!BaseElem->isDependentType() && BaseElem.isDestructedType()) { Diag(FD->getLocation(), diag::err_flexible_array_has_nontrivial_dtor) << FD->getDeclName() << FD->getType(); FD->setInvalidDecl(); EnclosingDecl->setInvalidDecl(); continue; } // Okay, we have a legal flexible array member at the end of the struct. Record->setHasFlexibleArrayMember(true); } else if (!FDTy->isDependentType() && RequireCompleteType(FD->getLocation(), FD->getType(), diag::err_field_incomplete)) { // Incomplete type FD->setInvalidDecl(); EnclosingDecl->setInvalidDecl(); continue; } else if (const RecordType *FDTTy = FDTy->getAs()) { if (Record && FDTTy->getDecl()->hasFlexibleArrayMember()) { // A type which contains a flexible array member is considered to be a // flexible array member. Record->setHasFlexibleArrayMember(true); if (!Record->isUnion()) { // If this is a struct/class and this is not the last element, reject // it. Note that GCC supports variable sized arrays in the middle of // structures. if (i + 1 != Fields.end()) Diag(FD->getLocation(), diag::ext_variable_sized_type_in_struct) << FD->getDeclName() << FD->getType(); else { // We support flexible arrays at the end of structs in // other structs as an extension. Diag(FD->getLocation(), diag::ext_flexible_array_in_struct) << FD->getDeclName(); } } } if (isa(EnclosingDecl) && RequireNonAbstractType(FD->getLocation(), FD->getType(), diag::err_abstract_type_in_decl, AbstractIvarType)) { // Ivars can not have abstract class types FD->setInvalidDecl(); } if (Record && FDTTy->getDecl()->hasObjectMember()) Record->setHasObjectMember(true); if (Record && FDTTy->getDecl()->hasVolatileMember()) Record->setHasVolatileMember(true); } else if (FDTy->isObjCObjectType()) { /// A field cannot be an Objective-c object Diag(FD->getLocation(), diag::err_statically_allocated_object) << FixItHint::CreateInsertion(FD->getLocation(), "*"); QualType T = Context.getObjCObjectPointerType(FD->getType()); FD->setType(T); } else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && Record && !ObjCFieldLifetimeErrReported && (!getLangOpts().CPlusPlus || Record->isUnion())) { // It's an error in ARC or Weak if a field has lifetime. // We don't want to report this in a system header, though, // so we just make the field unavailable. // FIXME: that's really not sufficient; we need to make the type // itself invalid to, say, initialize or copy. QualType T = FD->getType(); if (T.hasNonTrivialObjCLifetime()) { SourceLocation loc = FD->getLocation(); if (getSourceManager().isInSystemHeader(loc)) { if (!FD->hasAttr()) { FD->addAttr(UnavailableAttr::CreateImplicit(Context, "", UnavailableAttr::IR_ARCFieldWithOwnership, loc)); } } else { Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag) << T->isBlockPointerType() << Record->getTagKind(); } ObjCFieldLifetimeErrReported = true; } } else if (getLangOpts().ObjC1 && getLangOpts().getGC() != LangOptions::NonGC && Record && !Record->hasObjectMember()) { if (FD->getType()->isObjCObjectPointerType() || FD->getType().isObjCGCStrong()) Record->setHasObjectMember(true); else if (Context.getAsArrayType(FD->getType())) { QualType BaseType = Context.getBaseElementType(FD->getType()); if (BaseType->isRecordType() && BaseType->getAs()->getDecl()->hasObjectMember()) Record->setHasObjectMember(true); else if (BaseType->isObjCObjectPointerType() || BaseType.isObjCGCStrong()) Record->setHasObjectMember(true); } } if (Record && FD->getType().isVolatileQualified()) Record->setHasVolatileMember(true); // Keep track of the number of named members. if (FD->getIdentifier()) ++NumNamedMembers; } // Okay, we successfully defined 'Record'. if (Record) { bool Completed = false; if (CXXRecordDecl *CXXRecord = dyn_cast(Record)) { if (!CXXRecord->isInvalidDecl()) { // Set access bits correctly on the directly-declared conversions. for (CXXRecordDecl::conversion_iterator I = CXXRecord->conversion_begin(), E = CXXRecord->conversion_end(); I != E; ++I) I.setAccess((*I)->getAccess()); } if (!CXXRecord->isDependentType()) { if (CXXRecord->hasUserDeclaredDestructor()) { // Adjust user-defined destructor exception spec. if (getLangOpts().CPlusPlus11) AdjustDestructorExceptionSpec(CXXRecord, CXXRecord->getDestructor()); } if (!CXXRecord->isInvalidDecl()) { // Add any implicitly-declared members to this class. AddImplicitlyDeclaredMembersToClass(CXXRecord); // If we have virtual base classes, we may end up finding multiple // final overriders for a given virtual function. Check for this // problem now. if (CXXRecord->getNumVBases()) { CXXFinalOverriderMap FinalOverriders; CXXRecord->getFinalOverriders(FinalOverriders); for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(), MEnd = FinalOverriders.end(); M != MEnd; ++M) { for (OverridingMethods::iterator SO = M->second.begin(), SOEnd = M->second.end(); SO != SOEnd; ++SO) { assert(SO->second.size() > 0 && "Virtual function without overridding functions?"); if (SO->second.size() == 1) continue; // C++ [class.virtual]p2: // In a derived class, if a virtual member function of a base // class subobject has more than one final overrider the // program is ill-formed. Diag(Record->getLocation(), diag::err_multiple_final_overriders) << (const NamedDecl *)M->first << Record; Diag(M->first->getLocation(), diag::note_overridden_virtual_function); for (OverridingMethods::overriding_iterator OM = SO->second.begin(), OMEnd = SO->second.end(); OM != OMEnd; ++OM) Diag(OM->Method->getLocation(), diag::note_final_overrider) << (const NamedDecl *)M->first << OM->Method->getParent(); Record->setInvalidDecl(); } } CXXRecord->completeDefinition(&FinalOverriders); Completed = true; } } } } if (!Completed) Record->completeDefinition(); // We may have deferred checking for a deleted destructor. Check now. if (CXXRecordDecl *CXXRecord = dyn_cast(Record)) { auto *Dtor = CXXRecord->getDestructor(); if (Dtor && Dtor->isImplicit() && ShouldDeleteSpecialMember(Dtor, CXXDestructor)) SetDeclDeleted(Dtor, CXXRecord->getLocation()); } if (Record->hasAttrs()) { CheckAlignasUnderalignment(Record); if (const MSInheritanceAttr *IA = Record->getAttr()) checkMSInheritanceAttrOnDefinition(cast(Record), IA->getRange(), IA->getBestCase(), IA->getSemanticSpelling()); } // Check if the structure/union declaration is a type that can have zero // size in C. For C this is a language extension, for C++ it may cause // compatibility problems. bool CheckForZeroSize; if (!getLangOpts().CPlusPlus) { CheckForZeroSize = true; } else { // For C++ filter out types that cannot be referenced in C code. CXXRecordDecl *CXXRecord = cast(Record); CheckForZeroSize = CXXRecord->getLexicalDeclContext()->isExternCContext() && !CXXRecord->isDependentType() && CXXRecord->isCLike(); } if (CheckForZeroSize) { bool ZeroSize = true; bool IsEmpty = true; unsigned NonBitFields = 0; for (RecordDecl::field_iterator I = Record->field_begin(), E = Record->field_end(); (NonBitFields == 0 || ZeroSize) && I != E; ++I) { IsEmpty = false; if (I->isUnnamedBitfield()) { if (I->getBitWidthValue(Context) > 0) ZeroSize = false; } else { ++NonBitFields; QualType FieldType = I->getType(); if (FieldType->isIncompleteType() || !Context.getTypeSizeInChars(FieldType).isZero()) ZeroSize = false; } } // Empty structs are an extension in C (C99 6.7.2.1p7). They are // allowed in C++, but warn if its declaration is inside // extern "C" block. if (ZeroSize) { Diag(RecLoc, getLangOpts().CPlusPlus ? diag::warn_zero_size_struct_union_in_extern_c : diag::warn_zero_size_struct_union_compat) << IsEmpty << Record->isUnion() << (NonBitFields > 1); } // Structs without named members are extension in C (C99 6.7.2.1p7), // but are accepted by GCC. if (NonBitFields == 0 && !getLangOpts().CPlusPlus) { Diag(RecLoc, IsEmpty ? diag::ext_empty_struct_union : diag::ext_no_named_members_in_struct_union) << Record->isUnion(); } } } else { ObjCIvarDecl **ClsFields = reinterpret_cast(RecFields.data()); if (ObjCInterfaceDecl *ID = dyn_cast(EnclosingDecl)) { ID->setEndOfDefinitionLoc(RBrac); // Add ivar's to class's DeclContext. for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { ClsFields[i]->setLexicalDeclContext(ID); ID->addDecl(ClsFields[i]); } // Must enforce the rule that ivars in the base classes may not be // duplicates. if (ID->getSuperClass()) DiagnoseDuplicateIvars(ID, ID->getSuperClass()); } else if (ObjCImplementationDecl *IMPDecl = dyn_cast(EnclosingDecl)) { assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl"); for (unsigned I = 0, N = RecFields.size(); I != N; ++I) // Ivar declared in @implementation never belongs to the implementation. // Only it is in implementation's lexical context. ClsFields[I]->setLexicalDeclContext(IMPDecl); CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac); IMPDecl->setIvarLBraceLoc(LBrac); IMPDecl->setIvarRBraceLoc(RBrac); } else if (ObjCCategoryDecl *CDecl = dyn_cast(EnclosingDecl)) { // case of ivars in class extension; all other cases have been // reported as errors elsewhere. // FIXME. Class extension does not have a LocEnd field. // CDecl->setLocEnd(RBrac); // Add ivar's to class extension's DeclContext. // Diagnose redeclaration of private ivars. ObjCInterfaceDecl *IDecl = CDecl->getClassInterface(); for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { if (IDecl) { if (const ObjCIvarDecl *ClsIvar = IDecl->getIvarDecl(ClsFields[i]->getIdentifier())) { Diag(ClsFields[i]->getLocation(), diag::err_duplicate_ivar_declaration); Diag(ClsIvar->getLocation(), diag::note_previous_definition); continue; } for (const auto *Ext : IDecl->known_extensions()) { if (const ObjCIvarDecl *ClsExtIvar = Ext->getIvarDecl(ClsFields[i]->getIdentifier())) { Diag(ClsFields[i]->getLocation(), diag::err_duplicate_ivar_declaration); Diag(ClsExtIvar->getLocation(), diag::note_previous_definition); continue; } } } ClsFields[i]->setLexicalDeclContext(CDecl); CDecl->addDecl(ClsFields[i]); } CDecl->setIvarLBraceLoc(LBrac); CDecl->setIvarRBraceLoc(RBrac); } } if (Attr) ProcessDeclAttributeList(S, Record, Attr); } /// \brief Determine whether the given integral value is representable within /// the given type T. static bool isRepresentableIntegerValue(ASTContext &Context, llvm::APSInt &Value, QualType T) { assert(T->isIntegralType(Context) && "Integral type required!"); unsigned BitWidth = Context.getIntWidth(T); if (Value.isUnsigned() || Value.isNonNegative()) { if (T->isSignedIntegerOrEnumerationType()) --BitWidth; return Value.getActiveBits() <= BitWidth; } return Value.getMinSignedBits() <= BitWidth; } // \brief Given an integral type, return the next larger integral type // (or a NULL type of no such type exists). static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) { // FIXME: Int128/UInt128 support, which also needs to be introduced into // enum checking below. assert(T->isIntegralType(Context) && "Integral type required!"); const unsigned NumTypes = 4; QualType SignedIntegralTypes[NumTypes] = { Context.ShortTy, Context.IntTy, Context.LongTy, Context.LongLongTy }; QualType UnsignedIntegralTypes[NumTypes] = { Context.UnsignedShortTy, Context.UnsignedIntTy, Context.UnsignedLongTy, Context.UnsignedLongLongTy }; unsigned BitWidth = Context.getTypeSize(T); QualType *Types = T->isSignedIntegerOrEnumerationType()? SignedIntegralTypes : UnsignedIntegralTypes; for (unsigned I = 0; I != NumTypes; ++I) if (Context.getTypeSize(Types[I]) > BitWidth) return Types[I]; return QualType(); } EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, EnumConstantDecl *LastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, Expr *Val) { unsigned IntWidth = Context.getTargetInfo().getIntWidth(); llvm::APSInt EnumVal(IntWidth); QualType EltTy; if (Val && DiagnoseUnexpandedParameterPack(Val, UPPC_EnumeratorValue)) Val = nullptr; if (Val) Val = DefaultLvalueConversion(Val).get(); if (Val) { if (Enum->isDependentType() || Val->isTypeDependent()) EltTy = Context.DependentTy; else { SourceLocation ExpLoc; if (getLangOpts().CPlusPlus11 && Enum->isFixed() && !getLangOpts().MSVCCompat) { // C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the // constant-expression in the enumerator-definition shall be a converted // constant expression of the underlying type. EltTy = Enum->getIntegerType(); ExprResult Converted = CheckConvertedConstantExpression(Val, EltTy, EnumVal, CCEK_Enumerator); if (Converted.isInvalid()) Val = nullptr; else Val = Converted.get(); } else if (!Val->isValueDependent() && !(Val = VerifyIntegerConstantExpression(Val, &EnumVal).get())) { // C99 6.7.2.2p2: Make sure we have an integer constant expression. } else { if (Enum->isFixed()) { EltTy = Enum->getIntegerType(); // In Obj-C and Microsoft mode, require the enumeration value to be // representable in the underlying type of the enumeration. In C++11, // we perform a non-narrowing conversion as part of converted constant // expression checking. if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) { if (getLangOpts().MSVCCompat) { Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy; Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).get(); } else Diag(IdLoc, diag::err_enumerator_too_large) << EltTy; } else Val = ImpCastExprToType(Val, EltTy, EltTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast) .get(); } else if (getLangOpts().CPlusPlus) { // C++11 [dcl.enum]p5: // If the underlying type is not fixed, the type of each enumerator // is the type of its initializing value: // - If an initializer is specified for an enumerator, the // initializing value has the same type as the expression. EltTy = Val->getType(); } else { // C99 6.7.2.2p2: // The expression that defines the value of an enumeration constant // shall be an integer constant expression that has a value // representable as an int. // Complain if the value is not representable in an int. if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy)) Diag(IdLoc, diag::ext_enum_value_not_int) << EnumVal.toString(10) << Val->getSourceRange() << (EnumVal.isUnsigned() || EnumVal.isNonNegative()); else if (!Context.hasSameType(Val->getType(), Context.IntTy)) { // Force the type of the expression to 'int'. Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).get(); } EltTy = Val->getType(); } } } } if (!Val) { if (Enum->isDependentType()) EltTy = Context.DependentTy; else if (!LastEnumConst) { // C++0x [dcl.enum]p5: // If the underlying type is not fixed, the type of each enumerator // is the type of its initializing value: // - If no initializer is specified for the first enumerator, the // initializing value has an unspecified integral type. // // GCC uses 'int' for its unspecified integral type, as does // C99 6.7.2.2p3. if (Enum->isFixed()) { EltTy = Enum->getIntegerType(); } else { EltTy = Context.IntTy; } } else { // Assign the last value + 1. EnumVal = LastEnumConst->getInitVal(); ++EnumVal; EltTy = LastEnumConst->getType(); // Check for overflow on increment. if (EnumVal < LastEnumConst->getInitVal()) { // C++0x [dcl.enum]p5: // If the underlying type is not fixed, the type of each enumerator // is the type of its initializing value: // // - Otherwise the type of the initializing value is the same as // the type of the initializing value of the preceding enumerator // unless the incremented value is not representable in that type, // in which case the type is an unspecified integral type // sufficient to contain the incremented value. If no such type // exists, the program is ill-formed. QualType T = getNextLargerIntegralType(Context, EltTy); if (T.isNull() || Enum->isFixed()) { // There is no integral type larger enough to represent this // value. Complain, then allow the value to wrap around. EnumVal = LastEnumConst->getInitVal(); EnumVal = EnumVal.zext(EnumVal.getBitWidth() * 2); ++EnumVal; if (Enum->isFixed()) // When the underlying type is fixed, this is ill-formed. Diag(IdLoc, diag::err_enumerator_wrapped) << EnumVal.toString(10) << EltTy; else Diag(IdLoc, diag::ext_enumerator_increment_too_large) << EnumVal.toString(10); } else { EltTy = T; } // Retrieve the last enumerator's value, extent that type to the // type that is supposed to be large enough to represent the incremented // value, then increment. EnumVal = LastEnumConst->getInitVal(); EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType()); EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy)); ++EnumVal; // If we're not in C++, diagnose the overflow of enumerator values, // which in C99 means that the enumerator value is not representable in // an int (C99 6.7.2.2p2). However, we support GCC's extension that // permits enumerator values that are representable in some larger // integral type. if (!getLangOpts().CPlusPlus && !T.isNull()) Diag(IdLoc, diag::warn_enum_value_overflow); } else if (!getLangOpts().CPlusPlus && !isRepresentableIntegerValue(Context, EnumVal, EltTy)) { // Enforce C99 6.7.2.2p2 even when we compute the next value. Diag(IdLoc, diag::ext_enum_value_not_int) << EnumVal.toString(10) << 1; } } } if (!EltTy->isDependentType()) { // Make the enumerator value match the signedness and size of the // enumerator's type. EnumVal = EnumVal.extOrTrunc(Context.getIntWidth(EltTy)); EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType()); } return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy, Val, EnumVal); } Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II, SourceLocation IILoc) { if (!(getLangOpts().Modules || getLangOpts().ModulesLocalVisibility) || !getLangOpts().CPlusPlus) return SkipBodyInfo(); // We have an anonymous enum definition. Look up the first enumerator to // determine if we should merge the definition with an existing one and // skip the body. NamedDecl *PrevDecl = LookupSingleName(S, II, IILoc, LookupOrdinaryName, ForRedeclaration); auto *PrevECD = dyn_cast_or_null(PrevDecl); if (!PrevECD) return SkipBodyInfo(); EnumDecl *PrevED = cast(PrevECD->getDeclContext()); NamedDecl *Hidden; if (!PrevED->getDeclName() && !hasVisibleDefinition(PrevED, &Hidden)) { SkipBodyInfo Skip; Skip.Previous = Hidden; return Skip; } return SkipBodyInfo(); } Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, AttributeList *Attr, SourceLocation EqualLoc, Expr *Val) { EnumDecl *TheEnumDecl = cast(theEnumDecl); EnumConstantDecl *LastEnumConst = cast_or_null(lastEnumConst); // The scope passed in may not be a decl scope. Zip up the scope tree until // we find one that is. S = getNonFieldDeclScope(S); // Verify that there isn't already something declared with this name in this // scope. NamedDecl *PrevDecl = LookupSingleName(S, Id, IdLoc, LookupOrdinaryName, ForRedeclaration); if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(IdLoc, PrevDecl); // Just pretend that we didn't see the previous declaration. PrevDecl = nullptr; } // C++ [class.mem]p15: // If T is the name of a class, then each of the following shall have a name // different from T: // - every enumerator of every member of class T that is an unscoped // enumerated type if (getLangOpts().CPlusPlus && !TheEnumDecl->isScoped()) DiagnoseClassNameShadow(TheEnumDecl->getDeclContext(), DeclarationNameInfo(Id, IdLoc)); EnumConstantDecl *New = CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val); if (!New) return nullptr; if (PrevDecl) { // When in C++, we may get a TagDecl with the same name; in this case the // enum constant will 'hide' the tag. assert((getLangOpts().CPlusPlus || !isa(PrevDecl)) && "Received TagDecl when not in C++!"); if (!isa(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S) && shouldLinkPossiblyHiddenDecl(PrevDecl, New)) { if (isa(PrevDecl)) Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id; else Diag(IdLoc, diag::err_redefinition) << Id; notePreviousDefinition(PrevDecl, IdLoc); return nullptr; } } // Process attributes. if (Attr) ProcessDeclAttributeList(S, New, Attr); AddPragmaAttributes(S, New); // Register this decl in the current scope stack. New->setAccess(TheEnumDecl->getAccess()); PushOnScopeChains(New, S); ActOnDocumentableDecl(New); return New; } // Returns true when the enum initial expression does not trigger the // duplicate enum warning. A few common cases are exempted as follows: // Element2 = Element1 // Element2 = Element1 + 1 // Element2 = Element1 - 1 // Where Element2 and Element1 are from the same enum. static bool ValidDuplicateEnum(EnumConstantDecl *ECD, EnumDecl *Enum) { Expr *InitExpr = ECD->getInitExpr(); if (!InitExpr) return true; InitExpr = InitExpr->IgnoreImpCasts(); if (BinaryOperator *BO = dyn_cast(InitExpr)) { if (!BO->isAdditiveOp()) return true; IntegerLiteral *IL = dyn_cast(BO->getRHS()); if (!IL) return true; if (IL->getValue() != 1) return true; InitExpr = BO->getLHS(); } // This checks if the elements are from the same enum. DeclRefExpr *DRE = dyn_cast(InitExpr); if (!DRE) return true; EnumConstantDecl *EnumConstant = dyn_cast(DRE->getDecl()); if (!EnumConstant) return true; if (cast(TagDecl::castFromDeclContext(ECD->getDeclContext())) != Enum) return true; return false; } namespace { struct DupKey { int64_t val; bool isTombstoneOrEmptyKey; DupKey(int64_t val, bool isTombstoneOrEmptyKey) : val(val), isTombstoneOrEmptyKey(isTombstoneOrEmptyKey) {} }; static DupKey GetDupKey(const llvm::APSInt& Val) { return DupKey(Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue(), false); } struct DenseMapInfoDupKey { static DupKey getEmptyKey() { return DupKey(0, true); } static DupKey getTombstoneKey() { return DupKey(1, true); } static unsigned getHashValue(const DupKey Key) { return (unsigned)(Key.val * 37); } static bool isEqual(const DupKey& LHS, const DupKey& RHS) { return LHS.isTombstoneOrEmptyKey == RHS.isTombstoneOrEmptyKey && LHS.val == RHS.val; } }; } // end anonymous namespace // Emits a warning when an element is implicitly set a value that // a previous element has already been set to. static void CheckForDuplicateEnumValues(Sema &S, ArrayRef Elements, EnumDecl *Enum, QualType EnumType) { if (S.Diags.isIgnored(diag::warn_duplicate_enum_values, Enum->getLocation())) return; // Avoid anonymous enums if (!Enum->getIdentifier()) return; // Only check for small enums. if (Enum->getNumPositiveBits() > 63 || Enum->getNumNegativeBits() > 64) return; typedef SmallVector ECDVector; typedef SmallVector DuplicatesVector; typedef llvm::PointerUnion DeclOrVector; typedef llvm::DenseMap ValueToVectorMap; DuplicatesVector DupVector; ValueToVectorMap EnumMap; // Populate the EnumMap with all values represented by enum constants without // an initialier. for (unsigned i = 0, e = Elements.size(); i != e; ++i) { EnumConstantDecl *ECD = cast_or_null(Elements[i]); // Null EnumConstantDecl means a previous diagnostic has been emitted for // this constant. Skip this enum since it may be ill-formed. if (!ECD) { return; } if (ECD->getInitExpr()) continue; DupKey Key = GetDupKey(ECD->getInitVal()); DeclOrVector &Entry = EnumMap[Key]; // First time encountering this value. if (Entry.isNull()) Entry = ECD; } // Create vectors for any values that has duplicates. for (unsigned i = 0, e = Elements.size(); i != e; ++i) { EnumConstantDecl *ECD = cast(Elements[i]); if (!ValidDuplicateEnum(ECD, Enum)) continue; DupKey Key = GetDupKey(ECD->getInitVal()); DeclOrVector& Entry = EnumMap[Key]; if (Entry.isNull()) continue; if (EnumConstantDecl *D = Entry.dyn_cast()) { // Ensure constants are different. if (D == ECD) continue; // Create new vector and push values onto it. ECDVector *Vec = new ECDVector(); Vec->push_back(D); Vec->push_back(ECD); // Update entry to point to the duplicates vector. Entry = Vec; // Store the vector somewhere we can consult later for quick emission of // diagnostics. DupVector.push_back(Vec); continue; } ECDVector *Vec = Entry.get(); // Make sure constants are not added more than once. if (*Vec->begin() == ECD) continue; Vec->push_back(ECD); } // Emit diagnostics. for (DuplicatesVector::iterator DupVectorIter = DupVector.begin(), DupVectorEnd = DupVector.end(); DupVectorIter != DupVectorEnd; ++DupVectorIter) { ECDVector *Vec = *DupVectorIter; assert(Vec->size() > 1 && "ECDVector should have at least 2 elements."); // Emit warning for one enum constant. ECDVector::iterator I = Vec->begin(); S.Diag((*I)->getLocation(), diag::warn_duplicate_enum_values) << (*I)->getName() << (*I)->getInitVal().toString(10) << (*I)->getSourceRange(); ++I; // Emit one note for each of the remaining enum constants with // the same value. for (ECDVector::iterator E = Vec->end(); I != E; ++I) S.Diag((*I)->getLocation(), diag::note_duplicate_element) << (*I)->getName() << (*I)->getInitVal().toString(10) << (*I)->getSourceRange(); delete Vec; } } bool Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val, bool AllowMask) const { assert(ED->isClosedFlag() && "looking for value in non-flag or open enum"); assert(ED->isCompleteDefinition() && "expected enum definition"); auto R = FlagBitsCache.insert(std::make_pair(ED, llvm::APInt())); llvm::APInt &FlagBits = R.first->second; if (R.second) { for (auto *E : ED->enumerators()) { const auto &EVal = E->getInitVal(); // Only single-bit enumerators introduce new flag values. if (EVal.isPowerOf2()) FlagBits = FlagBits.zextOrSelf(EVal.getBitWidth()) | EVal; } } // A value is in a flag enum if either its bits are a subset of the enum's // flag bits (the first condition) or we are allowing masks and the same is // true of its complement (the second condition). When masks are allowed, we // allow the common idiom of ~(enum1 | enum2) to be a valid enum value. // // While it's true that any value could be used as a mask, the assumption is // that a mask will have all of the insignificant bits set. Anything else is // likely a logic error. llvm::APInt FlagMask = ~FlagBits.zextOrTrunc(Val.getBitWidth()); return !(FlagMask & Val) || (AllowMask && !(FlagMask & ~Val)); } void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, Decl *EnumDeclX, ArrayRef Elements, Scope *S, AttributeList *Attr) { EnumDecl *Enum = cast(EnumDeclX); QualType EnumType = Context.getTypeDeclType(Enum); if (Attr) ProcessDeclAttributeList(S, Enum, Attr); if (Enum->isDependentType()) { for (unsigned i = 0, e = Elements.size(); i != e; ++i) { EnumConstantDecl *ECD = cast_or_null(Elements[i]); if (!ECD) continue; ECD->setType(EnumType); } Enum->completeDefinition(Context.DependentTy, Context.DependentTy, 0, 0); return; } // TODO: If the result value doesn't fit in an int, it must be a long or long // long value. ISO C does not support this, but GCC does as an extension, // emit a warning. unsigned IntWidth = Context.getTargetInfo().getIntWidth(); unsigned CharWidth = Context.getTargetInfo().getCharWidth(); unsigned ShortWidth = Context.getTargetInfo().getShortWidth(); // Verify that all the values are okay, compute the size of the values, and // reverse the list. unsigned NumNegativeBits = 0; unsigned NumPositiveBits = 0; // Keep track of whether all elements have type int. bool AllElementsInt = true; for (unsigned i = 0, e = Elements.size(); i != e; ++i) { EnumConstantDecl *ECD = cast_or_null(Elements[i]); if (!ECD) continue; // Already issued a diagnostic. const llvm::APSInt &InitVal = ECD->getInitVal(); // Keep track of the size of positive and negative values. if (InitVal.isUnsigned() || InitVal.isNonNegative()) NumPositiveBits = std::max(NumPositiveBits, (unsigned)InitVal.getActiveBits()); else NumNegativeBits = std::max(NumNegativeBits, (unsigned)InitVal.getMinSignedBits()); // Keep track of whether every enum element has type int (very commmon). if (AllElementsInt) AllElementsInt = ECD->getType() == Context.IntTy; } // Figure out the type that should be used for this enum. QualType BestType; unsigned BestWidth; // C++0x N3000 [conv.prom]p3: // An rvalue of an unscoped enumeration type whose underlying // type is not fixed can be converted to an rvalue of the first // of the following types that can represent all the values of // the enumeration: int, unsigned int, long int, unsigned long // int, long long int, or unsigned long long int. // C99 6.4.4.3p2: // An identifier declared as an enumeration constant has type int. // The C99 rule is modified by a gcc extension QualType BestPromotionType; bool Packed = Enum->hasAttr(); // -fshort-enums is the equivalent to specifying the packed attribute on all // enum definitions. if (LangOpts.ShortEnums) Packed = true; if (Enum->isFixed()) { BestType = Enum->getIntegerType(); if (BestType->isPromotableIntegerType()) BestPromotionType = Context.getPromotedIntegerType(BestType); else BestPromotionType = BestType; BestWidth = Context.getIntWidth(BestType); } else if (NumNegativeBits) { // If there is a negative value, figure out the smallest integer type (of // int/long/longlong) that fits. // If it's packed, check also if it fits a char or a short. if (Packed && NumNegativeBits <= CharWidth && NumPositiveBits < CharWidth) { BestType = Context.SignedCharTy; BestWidth = CharWidth; } else if (Packed && NumNegativeBits <= ShortWidth && NumPositiveBits < ShortWidth) { BestType = Context.ShortTy; BestWidth = ShortWidth; } else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) { BestType = Context.IntTy; BestWidth = IntWidth; } else { BestWidth = Context.getTargetInfo().getLongWidth(); if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) { BestType = Context.LongTy; } else { BestWidth = Context.getTargetInfo().getLongLongWidth(); if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth) Diag(Enum->getLocation(), diag::ext_enum_too_large); BestType = Context.LongLongTy; } } BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType); } else { // If there is no negative value, figure out the smallest type that fits // all of the enumerator values. // If it's packed, check also if it fits a char or a short. if (Packed && NumPositiveBits <= CharWidth) { BestType = Context.UnsignedCharTy; BestPromotionType = Context.IntTy; BestWidth = CharWidth; } else if (Packed && NumPositiveBits <= ShortWidth) { BestType = Context.UnsignedShortTy; BestPromotionType = Context.IntTy; BestWidth = ShortWidth; } else if (NumPositiveBits <= IntWidth) { BestType = Context.UnsignedIntTy; BestWidth = IntWidth; BestPromotionType = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) ? Context.UnsignedIntTy : Context.IntTy; } else if (NumPositiveBits <= (BestWidth = Context.getTargetInfo().getLongWidth())) { BestType = Context.UnsignedLongTy; BestPromotionType = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) ? Context.UnsignedLongTy : Context.LongTy; } else { BestWidth = Context.getTargetInfo().getLongLongWidth(); assert(NumPositiveBits <= BestWidth && "How could an initializer get larger than ULL?"); BestType = Context.UnsignedLongLongTy; BestPromotionType = (NumPositiveBits == BestWidth || !getLangOpts().CPlusPlus) ? Context.UnsignedLongLongTy : Context.LongLongTy; } } // Loop over all of the enumerator constants, changing their types to match // the type of the enum if needed. for (auto *D : Elements) { auto *ECD = cast_or_null(D); if (!ECD) continue; // Already issued a diagnostic. // Standard C says the enumerators have int type, but we allow, as an // extension, the enumerators to be larger than int size. If each // enumerator value fits in an int, type it as an int, otherwise type it the // same as the enumerator decl itself. This means that in "enum { X = 1U }" // that X has type 'int', not 'unsigned'. // Determine whether the value fits into an int. llvm::APSInt InitVal = ECD->getInitVal(); // If it fits into an integer type, force it. Otherwise force it to match // the enum decl type. QualType NewTy; unsigned NewWidth; bool NewSign; if (!getLangOpts().CPlusPlus && !Enum->isFixed() && isRepresentableIntegerValue(Context, InitVal, Context.IntTy)) { NewTy = Context.IntTy; NewWidth = IntWidth; NewSign = true; } else if (ECD->getType() == BestType) { // Already the right type! if (getLangOpts().CPlusPlus) // C++ [dcl.enum]p4: Following the closing brace of an // enum-specifier, each enumerator has the type of its // enumeration. ECD->setType(EnumType); continue; } else { NewTy = BestType; NewWidth = BestWidth; NewSign = BestType->isSignedIntegerOrEnumerationType(); } // Adjust the APSInt value. InitVal = InitVal.extOrTrunc(NewWidth); InitVal.setIsSigned(NewSign); ECD->setInitVal(InitVal); // Adjust the Expr initializer and type. if (ECD->getInitExpr() && !Context.hasSameType(NewTy, ECD->getInitExpr()->getType())) ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy, CK_IntegralCast, ECD->getInitExpr(), /*base paths*/ nullptr, VK_RValue)); if (getLangOpts().CPlusPlus) // C++ [dcl.enum]p4: Following the closing brace of an // enum-specifier, each enumerator has the type of its // enumeration. ECD->setType(EnumType); else ECD->setType(NewTy); } Enum->completeDefinition(BestType, BestPromotionType, NumPositiveBits, NumNegativeBits); CheckForDuplicateEnumValues(*this, Elements, Enum, EnumType); if (Enum->isClosedFlag()) { for (Decl *D : Elements) { EnumConstantDecl *ECD = cast_or_null(D); if (!ECD) continue; // Already issued a diagnostic. llvm::APSInt InitVal = ECD->getInitVal(); if (InitVal != 0 && !InitVal.isPowerOf2() && !IsValueInFlagEnum(Enum, InitVal, true)) Diag(ECD->getLocation(), diag::warn_flag_enum_constant_out_of_range) << ECD << Enum; } } // Now that the enum type is defined, ensure it's not been underaligned. if (Enum->hasAttrs()) CheckAlignasUnderalignment(Enum); } Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, SourceLocation StartLoc, SourceLocation EndLoc) { StringLiteral *AsmString = cast(expr); FileScopeAsmDecl *New = FileScopeAsmDecl::Create(Context, CurContext, AsmString, StartLoc, EndLoc); CurContext->addDecl(New); return New; } static void checkModuleImportContext(Sema &S, Module *M, SourceLocation ImportLoc, DeclContext *DC, bool FromInclude = false) { SourceLocation ExternCLoc; if (auto *LSD = dyn_cast(DC)) { switch (LSD->getLanguage()) { case LinkageSpecDecl::lang_c: if (ExternCLoc.isInvalid()) ExternCLoc = LSD->getLocStart(); break; case LinkageSpecDecl::lang_cxx: break; } DC = LSD->getParent(); } while (isa(DC)) DC = DC->getParent(); if (!isa(DC)) { S.Diag(ImportLoc, (FromInclude && S.isModuleVisible(M)) ? diag::ext_module_import_not_at_top_level_noop : diag::err_module_import_not_at_top_level_fatal) << M->getFullModuleName() << DC; S.Diag(cast(DC)->getLocStart(), diag::note_module_import_not_at_top_level) << DC; } else if (!M->IsExternC && ExternCLoc.isValid()) { S.Diag(ImportLoc, diag::ext_module_import_in_extern_c) << M->getFullModuleName(); S.Diag(ExternCLoc, diag::note_extern_c_begins_here); } } Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, ModuleDeclKind MDK, ModuleIdPath Path) { // A module implementation unit requires that we are not compiling a module // of any kind. A module interface unit requires that we are not compiling a // module map. switch (getLangOpts().getCompilingModule()) { case LangOptions::CMK_None: // It's OK to compile a module interface as a normal translation unit. break; case LangOptions::CMK_ModuleInterface: if (MDK != ModuleDeclKind::Implementation) break; // We were asked to compile a module interface unit but this is a module // implementation unit. That indicates the 'export' is missing. Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch) << FixItHint::CreateInsertion(ModuleLoc, "export "); break; case LangOptions::CMK_ModuleMap: Diag(ModuleLoc, diag::err_module_decl_in_module_map_module); return nullptr; } // FIXME: Most of this work should be done by the preprocessor rather than // here, in order to support macro import. // Flatten the dots in a module name. Unlike Clang's hierarchical module map // modules, the dots here are just another character that can appear in a // module name. std::string ModuleName; for (auto &Piece : Path) { if (!ModuleName.empty()) ModuleName += "."; ModuleName += Piece.first->getName(); } // FIXME: If we've already seen a module-declaration, report an error. // If a module name was explicitly specified on the command line, it must be // correct. if (!getLangOpts().CurrentModule.empty() && getLangOpts().CurrentModule != ModuleName) { Diag(Path.front().second, diag::err_current_module_name_mismatch) << SourceRange(Path.front().second, Path.back().second) << getLangOpts().CurrentModule; return nullptr; } const_cast(getLangOpts()).CurrentModule = ModuleName; auto &Map = PP.getHeaderSearchInfo().getModuleMap(); Module *Mod; switch (MDK) { case ModuleDeclKind::Module: { // FIXME: Check we're not in a submodule. // We can't have parsed or imported a definition of this module or parsed a // module map defining it already. if (auto *M = Map.findModule(ModuleName)) { Diag(Path[0].second, diag::err_module_redefinition) << ModuleName; if (M->DefinitionLoc.isValid()) Diag(M->DefinitionLoc, diag::note_prev_module_definition); else if (const auto *FE = M->getASTFile()) Diag(M->DefinitionLoc, diag::note_prev_module_definition_from_ast_file) << FE->getName(); return nullptr; } // Create a Module for the module that we're defining. Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName); assert(Mod && "module creation should not fail"); break; } case ModuleDeclKind::Partition: // FIXME: Check we are in a submodule of the named module. return nullptr; case ModuleDeclKind::Implementation: std::pair ModuleNameLoc( PP.getIdentifierInfo(ModuleName), Path[0].second); Mod = getModuleLoader().loadModule(ModuleLoc, Path, Module::AllVisible, /*IsIncludeDirective=*/false); if (!Mod) return nullptr; break; } // Enter the semantic scope of the module. ModuleScopes.push_back({}); ModuleScopes.back().Module = Mod; ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules); VisibleModules.setVisible(Mod, ModuleLoc); // From now on, we have an owning module for all declarations we see. // However, those declarations are module-private unless explicitly // exported. Context.getTranslationUnitDecl()->setLocalOwningModule(Mod); // FIXME: Create a ModuleDecl. return nullptr; } DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, SourceLocation ImportLoc, ModuleIdPath Path) { Module *Mod = getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible, /*IsIncludeDirective=*/false); if (!Mod) return true; VisibleModules.setVisible(Mod, ImportLoc); checkModuleImportContext(*this, Mod, ImportLoc, CurContext); // FIXME: we should support importing a submodule within a different submodule // of the same top-level module. Until we do, make it an error rather than // silently ignoring the import. // Import-from-implementation is valid in the Modules TS. FIXME: Should we // warn on a redundant import of the current module? if (Mod->getTopLevelModuleName() == getLangOpts().CurrentModule && (getLangOpts().isCompilingModule() || !getLangOpts().ModulesTS)) Diag(ImportLoc, getLangOpts().isCompilingModule() ? diag::err_module_self_import : diag::err_module_import_in_implementation) << Mod->getFullModuleName() << getLangOpts().CurrentModule; SmallVector IdentifierLocs; Module *ModCheck = Mod; for (unsigned I = 0, N = Path.size(); I != N; ++I) { // If we've run out of module parents, just drop the remaining identifiers. // We need the length to be consistent. if (!ModCheck) break; ModCheck = ModCheck->Parent; IdentifierLocs.push_back(Path[I].second); } TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); ImportDecl *Import = ImportDecl::Create(Context, TU, StartLoc, Mod, IdentifierLocs); if (!ModuleScopes.empty()) Context.addModuleInitializer(ModuleScopes.back().Module, Import); TU->addDecl(Import); return Import; } void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true); BuildModuleInclude(DirectiveLoc, Mod); } void Sema::BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { // Determine whether we're in the #include buffer for a module. The #includes // in that buffer do not qualify as module imports; they're just an // implementation detail of us building the module. // // FIXME: Should we even get ActOnModuleInclude calls for those? bool IsInModuleIncludes = TUKind == TU_Module && getSourceManager().isWrittenInMainFile(DirectiveLoc); bool ShouldAddImport = !IsInModuleIncludes; // If this module import was due to an inclusion directive, create an // implicit import declaration to capture it in the AST. if (ShouldAddImport) { TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU, DirectiveLoc, Mod, DirectiveLoc); if (!ModuleScopes.empty()) Context.addModuleInitializer(ModuleScopes.back().Module, ImportD); TU->addDecl(ImportD); Consumer.HandleImplicitImportDecl(ImportD); } getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc); VisibleModules.setVisible(Mod, DirectiveLoc); } void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) { checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true); ModuleScopes.push_back({}); ModuleScopes.back().Module = Mod; if (getLangOpts().ModulesLocalVisibility) ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules); VisibleModules.setVisible(Mod, DirectiveLoc); // The enclosing context is now part of this module. // FIXME: Consider creating a child DeclContext to hold the entities // lexically within the module. if (getLangOpts().trackLocalOwningModule()) { for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) { cast(DC)->setModuleOwnershipKind( getLangOpts().ModulesLocalVisibility ? Decl::ModuleOwnershipKind::VisibleWhenImported : Decl::ModuleOwnershipKind::Visible); cast(DC)->setLocalOwningModule(Mod); } } } void Sema::ActOnModuleEnd(SourceLocation EomLoc, Module *Mod) { if (getLangOpts().ModulesLocalVisibility) { VisibleModules = std::move(ModuleScopes.back().OuterVisibleModules); // Leaving a module hides namespace names, so our visible namespace cache // is now out of date. VisibleNamespaceCache.clear(); } assert(!ModuleScopes.empty() && ModuleScopes.back().Module == Mod && "left the wrong module scope"); ModuleScopes.pop_back(); // We got to the end of processing a local module. Create an // ImportDecl as we would for an imported module. FileID File = getSourceManager().getFileID(EomLoc); SourceLocation DirectiveLoc; if (EomLoc == getSourceManager().getLocForEndOfFile(File)) { // We reached the end of a #included module header. Use the #include loc. assert(File != getSourceManager().getMainFileID() && "end of submodule in main source file"); DirectiveLoc = getSourceManager().getIncludeLoc(File); } else { // We reached an EOM pragma. Use the pragma location. DirectiveLoc = EomLoc; } BuildModuleInclude(DirectiveLoc, Mod); // Any further declarations are in whatever module we returned to. if (getLangOpts().trackLocalOwningModule()) { // The parser guarantees that this is the same context that we entered // the module within. for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) { cast(DC)->setLocalOwningModule(getCurrentModule()); if (!getCurrentModule()) cast(DC)->setModuleOwnershipKind( Decl::ModuleOwnershipKind::Unowned); } } } void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc, Module *Mod) { // Bail if we're not allowed to implicitly import a module here. if (isSFINAEContext() || !getLangOpts().ModulesErrorRecovery || VisibleModules.isVisible(Mod)) return; // Create the implicit import declaration. TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU, Loc, Mod, Loc); TU->addDecl(ImportD); Consumer.HandleImplicitImportDecl(ImportD); // Make the module visible. getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc); VisibleModules.setVisible(Mod, Loc); } /// We have parsed the start of an export declaration, including the '{' /// (if present). Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc, SourceLocation LBraceLoc) { ExportDecl *D = ExportDecl::Create(Context, CurContext, ExportLoc); // C++ Modules TS draft: // An export-declaration shall appear in the purview of a module other than // the global module. if (ModuleScopes.empty() || !ModuleScopes.back().Module || ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit) Diag(ExportLoc, diag::err_export_not_in_module_interface); // An export-declaration [...] shall not contain more than one // export keyword. // // The intent here is that an export-declaration cannot appear within another // export-declaration. if (D->isExported()) Diag(ExportLoc, diag::err_export_within_export); CurContext->addDecl(D); PushDeclContext(S, D); D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::VisibleWhenImported); return D; } /// Complete the definition of an export declaration. Decl *Sema::ActOnFinishExportDecl(Scope *S, Decl *D, SourceLocation RBraceLoc) { auto *ED = cast(D); if (RBraceLoc.isValid()) ED->setRBraceLoc(RBraceLoc); // FIXME: Diagnose export of internal-linkage declaration (including // anonymous namespace). PopDeclContext(); return D; } void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name, IdentifierInfo* AliasName, SourceLocation PragmaLoc, SourceLocation NameLoc, SourceLocation AliasNameLoc) { NamedDecl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName); AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit(Context, AliasName->getName(), AliasNameLoc); // If a declaration that: // 1) declares a function or a variable // 2) has external linkage // already exists, add a label attribute to it. if (PrevDecl && (isa(PrevDecl) || isa(PrevDecl))) { if (isDeclExternC(PrevDecl)) PrevDecl->addAttr(Attr); else Diag(PrevDecl->getLocation(), diag::warn_redefine_extname_not_applied) << /*Variable*/(isa(PrevDecl) ? 0 : 1) << PrevDecl; // Otherwise, add a label atttibute to ExtnameUndeclaredIdentifiers. } else (void)ExtnameUndeclaredIdentifiers.insert(std::make_pair(Name, Attr)); } void Sema::ActOnPragmaWeakID(IdentifierInfo* Name, SourceLocation PragmaLoc, SourceLocation NameLoc) { Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName); if (PrevDecl) { PrevDecl->addAttr(WeakAttr::CreateImplicit(Context, PragmaLoc)); } else { (void)WeakUndeclaredIdentifiers.insert( std::pair (Name, WeakInfo((IdentifierInfo*)nullptr, NameLoc))); } } void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name, IdentifierInfo* AliasName, SourceLocation PragmaLoc, SourceLocation NameLoc, SourceLocation AliasNameLoc) { Decl *PrevDecl = LookupSingleName(TUScope, AliasName, AliasNameLoc, LookupOrdinaryName); WeakInfo W = WeakInfo(Name, NameLoc); if (PrevDecl && (isa(PrevDecl) || isa(PrevDecl))) { if (!PrevDecl->hasAttr()) if (NamedDecl *ND = dyn_cast(PrevDecl)) DeclApplyPragmaWeak(TUScope, ND, W); } else { (void)WeakUndeclaredIdentifiers.insert( std::pair(AliasName, W)); } } Decl *Sema::getObjCDeclContext() const { return (dyn_cast_or_null(CurContext)); } Index: head/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- head/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp (revision 326908) +++ head/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp (revision 326909) @@ -1,14971 +1,14974 @@ //===------ SemaDeclCXX.cpp - Semantic Analysis for C++ Declarations ------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements semantic analysis for C++ declarations. // //===----------------------------------------------------------------------===// #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/CXXFieldCollector.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include #include using namespace clang; //===----------------------------------------------------------------------===// // CheckDefaultArgumentVisitor //===----------------------------------------------------------------------===// namespace { /// CheckDefaultArgumentVisitor - C++ [dcl.fct.default] Traverses /// the default argument of a parameter to determine whether it /// contains any ill-formed subexpressions. For example, this will /// diagnose the use of local variables or parameters within the /// default argument expression. class CheckDefaultArgumentVisitor : public StmtVisitor { Expr *DefaultArg; Sema *S; public: CheckDefaultArgumentVisitor(Expr *defarg, Sema *s) : DefaultArg(defarg), S(s) {} bool VisitExpr(Expr *Node); bool VisitDeclRefExpr(DeclRefExpr *DRE); bool VisitCXXThisExpr(CXXThisExpr *ThisE); bool VisitLambdaExpr(LambdaExpr *Lambda); bool VisitPseudoObjectExpr(PseudoObjectExpr *POE); }; /// VisitExpr - Visit all of the children of this expression. bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) { bool IsInvalid = false; for (Stmt *SubStmt : Node->children()) IsInvalid |= Visit(SubStmt); return IsInvalid; } /// VisitDeclRefExpr - Visit a reference to a declaration, to /// determine whether this declaration can be used in the default /// argument expression. bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) { NamedDecl *Decl = DRE->getDecl(); if (ParmVarDecl *Param = dyn_cast(Decl)) { // C++ [dcl.fct.default]p9 // Default arguments are evaluated each time the function is // called. The order of evaluation of function arguments is // unspecified. Consequently, parameters of a function shall not // be used in default argument expressions, even if they are not // evaluated. Parameters of a function declared before a default // argument expression are in scope and can hide namespace and // class member names. return S->Diag(DRE->getLocStart(), diag::err_param_default_argument_references_param) << Param->getDeclName() << DefaultArg->getSourceRange(); } else if (VarDecl *VDecl = dyn_cast(Decl)) { // C++ [dcl.fct.default]p7 // Local variables shall not be used in default argument // expressions. if (VDecl->isLocalVarDecl()) return S->Diag(DRE->getLocStart(), diag::err_param_default_argument_references_local) << VDecl->getDeclName() << DefaultArg->getSourceRange(); } return false; } /// VisitCXXThisExpr - Visit a C++ "this" expression. bool CheckDefaultArgumentVisitor::VisitCXXThisExpr(CXXThisExpr *ThisE) { // C++ [dcl.fct.default]p8: // The keyword this shall not be used in a default argument of a // member function. return S->Diag(ThisE->getLocStart(), diag::err_param_default_argument_references_this) << ThisE->getSourceRange(); } bool CheckDefaultArgumentVisitor::VisitPseudoObjectExpr(PseudoObjectExpr *POE) { bool Invalid = false; for (PseudoObjectExpr::semantics_iterator i = POE->semantics_begin(), e = POE->semantics_end(); i != e; ++i) { Expr *E = *i; // Look through bindings. if (OpaqueValueExpr *OVE = dyn_cast(E)) { E = OVE->getSourceExpr(); assert(E && "pseudo-object binding without source expression?"); } Invalid |= Visit(E); } return Invalid; } bool CheckDefaultArgumentVisitor::VisitLambdaExpr(LambdaExpr *Lambda) { // C++11 [expr.lambda.prim]p13: // A lambda-expression appearing in a default argument shall not // implicitly or explicitly capture any entity. if (Lambda->capture_begin() == Lambda->capture_end()) return false; return S->Diag(Lambda->getLocStart(), diag::err_lambda_capture_default_arg); } } void Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method) { // If we have an MSAny spec already, don't bother. if (!Method || ComputedEST == EST_MSAny) return; const FunctionProtoType *Proto = Method->getType()->getAs(); Proto = Self->ResolveExceptionSpec(CallLoc, Proto); if (!Proto) return; ExceptionSpecificationType EST = Proto->getExceptionSpecType(); // If we have a throw-all spec at this point, ignore the function. if (ComputedEST == EST_None) return; switch(EST) { // If this function can throw any exceptions, make a note of that. case EST_MSAny: case EST_None: ClearExceptions(); ComputedEST = EST; return; // FIXME: If the call to this decl is using any of its default arguments, we // need to search them for potentially-throwing calls. // If this function has a basic noexcept, it doesn't affect the outcome. case EST_BasicNoexcept: return; // If we're still at noexcept(true) and there's a nothrow() callee, // change to that specification. case EST_DynamicNone: if (ComputedEST == EST_BasicNoexcept) ComputedEST = EST_DynamicNone; return; // Check out noexcept specs. case EST_ComputedNoexcept: { FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(Self->Context); assert(NR != FunctionProtoType::NR_NoNoexcept && "Must have noexcept result for EST_ComputedNoexcept."); assert(NR != FunctionProtoType::NR_Dependent && "Should not generate implicit declarations for dependent cases, " "and don't know how to handle them anyway."); // noexcept(false) -> no spec on the new function if (NR == FunctionProtoType::NR_Throw) { ClearExceptions(); ComputedEST = EST_None; } // noexcept(true) won't change anything either. return; } default: break; } assert(EST == EST_Dynamic && "EST case not considered earlier."); assert(ComputedEST != EST_None && "Shouldn't collect exceptions when throw-all is guaranteed."); ComputedEST = EST_Dynamic; // Record the exceptions in this function's exception specification. for (const auto &E : Proto->exceptions()) if (ExceptionsSeen.insert(Self->Context.getCanonicalType(E)).second) Exceptions.push_back(E); } void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) { if (!E || ComputedEST == EST_MSAny) return; // FIXME: // // C++0x [except.spec]p14: // [An] implicit exception-specification specifies the type-id T if and // only if T is allowed by the exception-specification of a function directly // invoked by f's implicit definition; f shall allow all exceptions if any // function it directly invokes allows all exceptions, and f shall allow no // exceptions if every function it directly invokes allows no exceptions. // // Note in particular that if an implicit exception-specification is generated // for a function containing a throw-expression, that specification can still // be noexcept(true). // // Note also that 'directly invoked' is not defined in the standard, and there // is no indication that we should only consider potentially-evaluated calls. // // Ultimately we should implement the intent of the standard: the exception // specification should be the set of exceptions which can be thrown by the // implicit definition. For now, we assume that any non-nothrow expression can // throw any exception. if (Self->canThrow(E)) ComputedEST = EST_None; } bool Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg, SourceLocation EqualLoc) { if (RequireCompleteType(Param->getLocation(), Param->getType(), diag::err_typecheck_decl_incomplete_type)) { Param->setInvalidDecl(); return true; } // C++ [dcl.fct.default]p5 // A default argument expression is implicitly converted (clause // 4) to the parameter type. The default argument expression has // the same semantic constraints as the initializer expression in // a declaration of a variable of the parameter type, using the // copy-initialization semantics (8.5). InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, Param); InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(), EqualLoc); InitializationSequence InitSeq(*this, Entity, Kind, Arg); ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Arg); if (Result.isInvalid()) return true; Arg = Result.getAs(); CheckCompletedExpr(Arg, EqualLoc); Arg = MaybeCreateExprWithCleanups(Arg); // Okay: add the default argument to the parameter Param->setDefaultArg(Arg); // We have already instantiated this parameter; provide each of the // instantiations with the uninstantiated default argument. UnparsedDefaultArgInstantiationsMap::iterator InstPos = UnparsedDefaultArgInstantiations.find(Param); if (InstPos != UnparsedDefaultArgInstantiations.end()) { for (unsigned I = 0, N = InstPos->second.size(); I != N; ++I) InstPos->second[I]->setUninstantiatedDefaultArg(Arg); // We're done tracking this parameter's instantiations. UnparsedDefaultArgInstantiations.erase(InstPos); } return false; } /// ActOnParamDefaultArgument - Check whether the default argument /// provided for a function parameter is well-formed. If so, attach it /// to the parameter declaration. void Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, Expr *DefaultArg) { if (!param || !DefaultArg) return; ParmVarDecl *Param = cast(param); UnparsedDefaultArgLocs.erase(Param); // Default arguments are only permitted in C++ if (!getLangOpts().CPlusPlus) { Diag(EqualLoc, diag::err_param_default_argument) << DefaultArg->getSourceRange(); Param->setInvalidDecl(); return; } // Check for unexpanded parameter packs. if (DiagnoseUnexpandedParameterPack(DefaultArg, UPPC_DefaultArgument)) { Param->setInvalidDecl(); return; } // C++11 [dcl.fct.default]p3 // A default argument expression [...] shall not be specified for a // parameter pack. if (Param->isParameterPack()) { Diag(EqualLoc, diag::err_param_default_argument_on_parameter_pack) << DefaultArg->getSourceRange(); return; } // Check that the default argument is well-formed CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this); if (DefaultArgChecker.Visit(DefaultArg)) { Param->setInvalidDecl(); return; } SetParamDefaultArgument(Param, DefaultArg, EqualLoc); } /// ActOnParamUnparsedDefaultArgument - We've seen a default /// argument for a function parameter, but we can't parse it yet /// because we're inside a class definition. Note that this default /// argument will be parsed later. void Sema::ActOnParamUnparsedDefaultArgument(Decl *param, SourceLocation EqualLoc, SourceLocation ArgLoc) { if (!param) return; ParmVarDecl *Param = cast(param); Param->setUnparsedDefaultArg(); UnparsedDefaultArgLocs[Param] = ArgLoc; } /// ActOnParamDefaultArgumentError - Parsing or semantic analysis of /// the default argument for the parameter param failed. void Sema::ActOnParamDefaultArgumentError(Decl *param, SourceLocation EqualLoc) { if (!param) return; ParmVarDecl *Param = cast(param); Param->setInvalidDecl(); UnparsedDefaultArgLocs.erase(Param); Param->setDefaultArg(new(Context) OpaqueValueExpr(EqualLoc, Param->getType().getNonReferenceType(), VK_RValue)); } /// CheckExtraCXXDefaultArguments - Check for any extra default /// arguments in the declarator, which is not a function declaration /// or definition and therefore is not permitted to have default /// arguments. This routine should be invoked for every declarator /// that is not a function declaration or definition. void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { // C++ [dcl.fct.default]p3 // A default argument expression shall be specified only in the // parameter-declaration-clause of a function declaration or in a // template-parameter (14.1). It shall not be specified for a // parameter pack. If it is specified in a // parameter-declaration-clause, it shall not occur within a // declarator or abstract-declarator of a parameter-declaration. bool MightBeFunction = D.isFunctionDeclarationContext(); for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { DeclaratorChunk &chunk = D.getTypeObject(i); if (chunk.Kind == DeclaratorChunk::Function) { if (MightBeFunction) { // This is a function declaration. It can have default arguments, but // keep looking in case its return type is a function type with default // arguments. MightBeFunction = false; continue; } for (unsigned argIdx = 0, e = chunk.Fun.NumParams; argIdx != e; ++argIdx) { ParmVarDecl *Param = cast(chunk.Fun.Params[argIdx].Param); if (Param->hasUnparsedDefaultArg()) { std::unique_ptr Toks = std::move(chunk.Fun.Params[argIdx].DefaultArgTokens); SourceRange SR; if (Toks->size() > 1) SR = SourceRange((*Toks)[1].getLocation(), Toks->back().getLocation()); else SR = UnparsedDefaultArgLocs[Param]; Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) << SR; } else if (Param->getDefaultArg()) { Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) << Param->getDefaultArg()->getSourceRange(); Param->setDefaultArg(nullptr); } } } else if (chunk.Kind != DeclaratorChunk::Paren) { MightBeFunction = false; } } } static bool functionDeclHasDefaultArgument(const FunctionDecl *FD) { for (unsigned NumParams = FD->getNumParams(); NumParams > 0; --NumParams) { const ParmVarDecl *PVD = FD->getParamDecl(NumParams-1); if (!PVD->hasDefaultArg()) return false; if (!PVD->hasInheritedDefaultArg()) return true; } return false; } /// MergeCXXFunctionDecl - Merge two declarations of the same C++ /// function, once we already know that they have the same /// type. Subroutine of MergeFunctionDecl. Returns true if there was an /// error, false otherwise. bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S) { bool Invalid = false; // The declaration context corresponding to the scope is the semantic // parent, unless this is a local function declaration, in which case // it is that surrounding function. DeclContext *ScopeDC = New->isLocalExternDecl() ? New->getLexicalDeclContext() : New->getDeclContext(); // Find the previous declaration for the purpose of default arguments. FunctionDecl *PrevForDefaultArgs = Old; for (/**/; PrevForDefaultArgs; // Don't bother looking back past the latest decl if this is a local // extern declaration; nothing else could work. PrevForDefaultArgs = New->isLocalExternDecl() ? nullptr : PrevForDefaultArgs->getPreviousDecl()) { // Ignore hidden declarations. if (!LookupResult::isVisible(*this, PrevForDefaultArgs)) continue; if (S && !isDeclInScope(PrevForDefaultArgs, ScopeDC, S) && !New->isCXXClassMember()) { // Ignore default arguments of old decl if they are not in // the same scope and this is not an out-of-line definition of // a member function. continue; } if (PrevForDefaultArgs->isLocalExternDecl() != New->isLocalExternDecl()) { // If only one of these is a local function declaration, then they are // declared in different scopes, even though isDeclInScope may think // they're in the same scope. (If both are local, the scope check is // sufficient, and if neither is local, then they are in the same scope.) continue; } // We found the right previous declaration. break; } // C++ [dcl.fct.default]p4: // For non-template functions, default arguments can be added in // later declarations of a function in the same // scope. Declarations in different scopes have completely // distinct sets of default arguments. That is, declarations in // inner scopes do not acquire default arguments from // declarations in outer scopes, and vice versa. In a given // function declaration, all parameters subsequent to a // parameter with a default argument shall have default // arguments supplied in this or previous declarations. A // default argument shall not be redefined by a later // declaration (not even to the same value). // // C++ [dcl.fct.default]p6: // Except for member functions of class templates, the default arguments // in a member function definition that appears outside of the class // definition are added to the set of default arguments provided by the // member function declaration in the class definition. for (unsigned p = 0, NumParams = PrevForDefaultArgs ? PrevForDefaultArgs->getNumParams() : 0; p < NumParams; ++p) { ParmVarDecl *OldParam = PrevForDefaultArgs->getParamDecl(p); ParmVarDecl *NewParam = New->getParamDecl(p); bool OldParamHasDfl = OldParam ? OldParam->hasDefaultArg() : false; bool NewParamHasDfl = NewParam->hasDefaultArg(); if (OldParamHasDfl && NewParamHasDfl) { unsigned DiagDefaultParamID = diag::err_param_default_argument_redefinition; // MSVC accepts that default parameters be redefined for member functions // of template class. The new default parameter's value is ignored. Invalid = true; if (getLangOpts().MicrosoftExt) { CXXMethodDecl *MD = dyn_cast(New); if (MD && MD->getParent()->getDescribedClassTemplate()) { // Merge the old default argument into the new parameter. NewParam->setHasInheritedDefaultArg(); if (OldParam->hasUninstantiatedDefaultArg()) NewParam->setUninstantiatedDefaultArg( OldParam->getUninstantiatedDefaultArg()); else NewParam->setDefaultArg(OldParam->getInit()); DiagDefaultParamID = diag::ext_param_default_argument_redefinition; Invalid = false; } } // FIXME: If we knew where the '=' was, we could easily provide a fix-it // hint here. Alternatively, we could walk the type-source information // for NewParam to find the last source location in the type... but it // isn't worth the effort right now. This is the kind of test case that // is hard to get right: // int f(int); // void g(int (*fp)(int) = f); // void g(int (*fp)(int) = &f); Diag(NewParam->getLocation(), DiagDefaultParamID) << NewParam->getDefaultArgRange(); // Look for the function declaration where the default argument was // actually written, which may be a declaration prior to Old. for (auto Older = PrevForDefaultArgs; OldParam->hasInheritedDefaultArg(); /**/) { Older = Older->getPreviousDecl(); OldParam = Older->getParamDecl(p); } Diag(OldParam->getLocation(), diag::note_previous_definition) << OldParam->getDefaultArgRange(); } else if (OldParamHasDfl) { // Merge the old default argument into the new parameter unless the new // function is a friend declaration in a template class. In the latter // case the default arguments will be inherited when the friend // declaration will be instantiated. if (New->getFriendObjectKind() == Decl::FOK_None || !New->getLexicalDeclContext()->isDependentContext()) { // It's important to use getInit() here; getDefaultArg() // strips off any top-level ExprWithCleanups. NewParam->setHasInheritedDefaultArg(); if (OldParam->hasUnparsedDefaultArg()) NewParam->setUnparsedDefaultArg(); else if (OldParam->hasUninstantiatedDefaultArg()) NewParam->setUninstantiatedDefaultArg( OldParam->getUninstantiatedDefaultArg()); else NewParam->setDefaultArg(OldParam->getInit()); } } else if (NewParamHasDfl) { if (New->getDescribedFunctionTemplate()) { // Paragraph 4, quoted above, only applies to non-template functions. Diag(NewParam->getLocation(), diag::err_param_default_argument_template_redecl) << NewParam->getDefaultArgRange(); Diag(PrevForDefaultArgs->getLocation(), diag::note_template_prev_declaration) << false; } else if (New->getTemplateSpecializationKind() != TSK_ImplicitInstantiation && New->getTemplateSpecializationKind() != TSK_Undeclared) { // C++ [temp.expr.spec]p21: // Default function arguments shall not be specified in a declaration // or a definition for one of the following explicit specializations: // - the explicit specialization of a function template; // - the explicit specialization of a member function template; // - the explicit specialization of a member function of a class // template where the class template specialization to which the // member function specialization belongs is implicitly // instantiated. Diag(NewParam->getLocation(), diag::err_template_spec_default_arg) << (New->getTemplateSpecializationKind() ==TSK_ExplicitSpecialization) << New->getDeclName() << NewParam->getDefaultArgRange(); } else if (New->getDeclContext()->isDependentContext()) { // C++ [dcl.fct.default]p6 (DR217): // Default arguments for a member function of a class template shall // be specified on the initial declaration of the member function // within the class template. // // Reading the tea leaves a bit in DR217 and its reference to DR205 // leads me to the conclusion that one cannot add default function // arguments for an out-of-line definition of a member function of a // dependent type. int WhichKind = 2; if (CXXRecordDecl *Record = dyn_cast(New->getDeclContext())) { if (Record->getDescribedClassTemplate()) WhichKind = 0; else if (isa(Record)) WhichKind = 1; else WhichKind = 2; } Diag(NewParam->getLocation(), diag::err_param_default_argument_member_template_redecl) << WhichKind << NewParam->getDefaultArgRange(); } } } // DR1344: If a default argument is added outside a class definition and that // default argument makes the function a special member function, the program // is ill-formed. This can only happen for constructors. if (isa(New) && New->getMinRequiredArguments() < Old->getMinRequiredArguments()) { CXXSpecialMember NewSM = getSpecialMember(cast(New)), OldSM = getSpecialMember(cast(Old)); if (NewSM != OldSM) { ParmVarDecl *NewParam = New->getParamDecl(New->getMinRequiredArguments()); assert(NewParam->hasDefaultArg()); Diag(NewParam->getLocation(), diag::err_default_arg_makes_ctor_special) << NewParam->getDefaultArgRange() << NewSM; Diag(Old->getLocation(), diag::note_previous_declaration); } } const FunctionDecl *Def; // C++11 [dcl.constexpr]p1: If any declaration of a function or function // template has a constexpr specifier then all its declarations shall // contain the constexpr specifier. if (New->isConstexpr() != Old->isConstexpr()) { Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch) << New << New->isConstexpr(); Diag(Old->getLocation(), diag::note_previous_declaration); Invalid = true; } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() && Old->isDefined(Def) && // If a friend function is inlined but does not have 'inline' // specifier, it is a definition. Do not report attribute conflict // in this case, redefinition will be diagnosed later. (New->isInlineSpecified() || New->getFriendObjectKind() == Decl::FOK_None)) { // C++11 [dcl.fcn.spec]p4: // If the definition of a function appears in a translation unit before its // first declaration as inline, the program is ill-formed. Diag(New->getLocation(), diag::err_inline_decl_follows_def) << New; Diag(Def->getLocation(), diag::note_previous_definition); Invalid = true; } // FIXME: It's not clear what should happen if multiple declarations of a // deduction guide have different explicitness. For now at least we simply // reject any case where the explicitness changes. auto *NewGuide = dyn_cast(New); if (NewGuide && NewGuide->isExplicitSpecified() != cast(Old)->isExplicitSpecified()) { Diag(New->getLocation(), diag::err_deduction_guide_explicit_mismatch) << NewGuide->isExplicitSpecified(); Diag(Old->getLocation(), diag::note_previous_declaration); } // C++11 [dcl.fct.default]p4: If a friend declaration specifies a default // argument expression, that declaration shall be a definition and shall be // the only declaration of the function or function template in the // translation unit. if (Old->getFriendObjectKind() == Decl::FOK_Undeclared && functionDeclHasDefaultArgument(Old)) { Diag(New->getLocation(), diag::err_friend_decl_with_def_arg_redeclared); Diag(Old->getLocation(), diag::note_previous_declaration); Invalid = true; } return Invalid; } NamedDecl * Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists) { assert(D.isDecompositionDeclarator()); const DecompositionDeclarator &Decomp = D.getDecompositionDeclarator(); // The syntax only allows a decomposition declarator as a simple-declaration // or a for-range-declaration, but we parse it in more cases than that. if (!D.mayHaveDecompositionDeclarator()) { Diag(Decomp.getLSquareLoc(), diag::err_decomp_decl_context) << Decomp.getSourceRange(); return nullptr; } if (!TemplateParamLists.empty()) { // FIXME: There's no rule against this, but there are also no rules that // would actually make it usable, so we reject it for now. Diag(TemplateParamLists.front()->getTemplateLoc(), diag::err_decomp_decl_template); return nullptr; } Diag(Decomp.getLSquareLoc(), getLangOpts().CPlusPlus1z ? diag::warn_cxx14_compat_decomp_decl : diag::ext_decomp_decl) << Decomp.getSourceRange(); // The semantic context is always just the current context. DeclContext *const DC = CurContext; // C++1z [dcl.dcl]/8: // The decl-specifier-seq shall contain only the type-specifier auto // and cv-qualifiers. auto &DS = D.getDeclSpec(); { SmallVector BadSpecifiers; SmallVector BadSpecifierLocs; if (auto SCS = DS.getStorageClassSpec()) { BadSpecifiers.push_back(DeclSpec::getSpecifierName(SCS)); BadSpecifierLocs.push_back(DS.getStorageClassSpecLoc()); } if (auto TSCS = DS.getThreadStorageClassSpec()) { BadSpecifiers.push_back(DeclSpec::getSpecifierName(TSCS)); BadSpecifierLocs.push_back(DS.getThreadStorageClassSpecLoc()); } if (DS.isConstexprSpecified()) { BadSpecifiers.push_back("constexpr"); BadSpecifierLocs.push_back(DS.getConstexprSpecLoc()); } if (DS.isInlineSpecified()) { BadSpecifiers.push_back("inline"); BadSpecifierLocs.push_back(DS.getInlineSpecLoc()); } if (!BadSpecifiers.empty()) { auto &&Err = Diag(BadSpecifierLocs.front(), diag::err_decomp_decl_spec); Err << (int)BadSpecifiers.size() << llvm::join(BadSpecifiers.begin(), BadSpecifiers.end(), " "); // Don't add FixItHints to remove the specifiers; we do still respect // them when building the underlying variable. for (auto Loc : BadSpecifierLocs) Err << SourceRange(Loc, Loc); } // We can't recover from it being declared as a typedef. if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) return nullptr; } TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType R = TInfo->getType(); if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, UPPC_DeclarationType)) D.setInvalidType(); // The syntax only allows a single ref-qualifier prior to the decomposition // declarator. No other declarator chunks are permitted. Also check the type // specifier here. if (DS.getTypeSpecType() != DeclSpec::TST_auto || D.hasGroupingParens() || D.getNumTypeObjects() > 1 || (D.getNumTypeObjects() == 1 && D.getTypeObject(0).Kind != DeclaratorChunk::Reference)) { Diag(Decomp.getLSquareLoc(), (D.hasGroupingParens() || (D.getNumTypeObjects() && D.getTypeObject(0).Kind == DeclaratorChunk::Paren)) ? diag::err_decomp_decl_parens : diag::err_decomp_decl_type) << R; // In most cases, there's no actual problem with an explicitly-specified // type, but a function type won't work here, and ActOnVariableDeclarator // shouldn't be called for such a type. if (R->isFunctionType()) D.setInvalidType(); } // Build the BindingDecls. SmallVector Bindings; // Build the BindingDecls. for (auto &B : D.getDecompositionDeclarator().bindings()) { // Check for name conflicts. DeclarationNameInfo NameInfo(B.Name, B.NameLoc); LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); LookupName(Previous, S, /*CreateBuiltins*/DC->getRedeclContext()->isTranslationUnit()); // It's not permitted to shadow a template parameter name. if (Previous.isSingleResult() && Previous.getFoundDecl()->isTemplateParameter()) { DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), Previous.getFoundDecl()); Previous.clear(); } bool ConsiderLinkage = DC->isFunctionOrMethod() && DS.getStorageClassSpec() == DeclSpec::SCS_extern; FilterLookupForScope(Previous, DC, S, ConsiderLinkage, /*AllowInlineNamespace*/false); if (!Previous.empty()) { auto *Old = Previous.getRepresentativeDecl(); Diag(B.NameLoc, diag::err_redefinition) << B.Name; Diag(Old->getLocation(), diag::note_previous_definition); } auto *BD = BindingDecl::Create(Context, DC, B.NameLoc, B.Name); PushOnScopeChains(BD, S, true); Bindings.push_back(BD); ParsingInitForAutoVars.insert(BD); } // There are no prior lookup results for the variable itself, because it // is unnamed. DeclarationNameInfo NameInfo((IdentifierInfo *)nullptr, Decomp.getLSquareLoc()); LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); // Build the variable that holds the non-decomposed object. bool AddToScope = true; NamedDecl *New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous, MultiTemplateParamsArg(), AddToScope, Bindings); - CurContext->addHiddenDecl(New); + if (AddToScope) { + S->AddDecl(New); + CurContext->addHiddenDecl(New); + } if (isInOpenMPDeclareTargetContext()) checkDeclIsAllowedInOpenMPTarget(nullptr, New); return New; } static bool checkSimpleDecomposition( Sema &S, ArrayRef Bindings, ValueDecl *Src, QualType DecompType, const llvm::APSInt &NumElems, QualType ElemType, llvm::function_ref GetInit) { if ((int64_t)Bindings.size() != NumElems) { S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) << DecompType << (unsigned)Bindings.size() << NumElems.toString(10) << (NumElems < Bindings.size()); return true; } unsigned I = 0; for (auto *B : Bindings) { SourceLocation Loc = B->getLocation(); ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc); if (E.isInvalid()) return true; E = GetInit(Loc, E.get(), I++); if (E.isInvalid()) return true; B->setBinding(ElemType, E.get()); } return false; } static bool checkArrayLikeDecomposition(Sema &S, ArrayRef Bindings, ValueDecl *Src, QualType DecompType, const llvm::APSInt &NumElems, QualType ElemType) { return checkSimpleDecomposition( S, Bindings, Src, DecompType, NumElems, ElemType, [&](SourceLocation Loc, Expr *Base, unsigned I) -> ExprResult { ExprResult E = S.ActOnIntegerConstant(Loc, I); if (E.isInvalid()) return ExprError(); return S.CreateBuiltinArraySubscriptExpr(Base, Loc, E.get(), Loc); }); } static bool checkArrayDecomposition(Sema &S, ArrayRef Bindings, ValueDecl *Src, QualType DecompType, const ConstantArrayType *CAT) { return checkArrayLikeDecomposition(S, Bindings, Src, DecompType, llvm::APSInt(CAT->getSize()), CAT->getElementType()); } static bool checkVectorDecomposition(Sema &S, ArrayRef Bindings, ValueDecl *Src, QualType DecompType, const VectorType *VT) { return checkArrayLikeDecomposition( S, Bindings, Src, DecompType, llvm::APSInt::get(VT->getNumElements()), S.Context.getQualifiedType(VT->getElementType(), DecompType.getQualifiers())); } static bool checkComplexDecomposition(Sema &S, ArrayRef Bindings, ValueDecl *Src, QualType DecompType, const ComplexType *CT) { return checkSimpleDecomposition( S, Bindings, Src, DecompType, llvm::APSInt::get(2), S.Context.getQualifiedType(CT->getElementType(), DecompType.getQualifiers()), [&](SourceLocation Loc, Expr *Base, unsigned I) -> ExprResult { return S.CreateBuiltinUnaryOp(Loc, I ? UO_Imag : UO_Real, Base); }); } static std::string printTemplateArgs(const PrintingPolicy &PrintingPolicy, TemplateArgumentListInfo &Args) { SmallString<128> SS; llvm::raw_svector_ostream OS(SS); bool First = true; for (auto &Arg : Args.arguments()) { if (!First) OS << ", "; Arg.getArgument().print(PrintingPolicy, OS); First = false; } return OS.str(); } static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup, SourceLocation Loc, StringRef Trait, TemplateArgumentListInfo &Args, unsigned DiagID) { auto DiagnoseMissing = [&] { if (DiagID) S.Diag(Loc, DiagID) << printTemplateArgs(S.Context.getPrintingPolicy(), Args); return true; }; // FIXME: Factor out duplication with lookupPromiseType in SemaCoroutine. NamespaceDecl *Std = S.getStdNamespace(); if (!Std) return DiagnoseMissing(); // Look up the trait itself, within namespace std. We can diagnose various // problems with this lookup even if we've been asked to not diagnose a // missing specialization, because this can only fail if the user has been // declaring their own names in namespace std or we don't support the // standard library implementation in use. LookupResult Result(S, &S.PP.getIdentifierTable().get(Trait), Loc, Sema::LookupOrdinaryName); if (!S.LookupQualifiedName(Result, Std)) return DiagnoseMissing(); if (Result.isAmbiguous()) return true; ClassTemplateDecl *TraitTD = Result.getAsSingle(); if (!TraitTD) { Result.suppressDiagnostics(); NamedDecl *Found = *Result.begin(); S.Diag(Loc, diag::err_std_type_trait_not_class_template) << Trait; S.Diag(Found->getLocation(), diag::note_declared_at); return true; } // Build the template-id. QualType TraitTy = S.CheckTemplateIdType(TemplateName(TraitTD), Loc, Args); if (TraitTy.isNull()) return true; if (!S.isCompleteType(Loc, TraitTy)) { if (DiagID) S.RequireCompleteType( Loc, TraitTy, DiagID, printTemplateArgs(S.Context.getPrintingPolicy(), Args)); return true; } CXXRecordDecl *RD = TraitTy->getAsCXXRecordDecl(); assert(RD && "specialization of class template is not a class?"); // Look up the member of the trait type. S.LookupQualifiedName(TraitMemberLookup, RD); return TraitMemberLookup.isAmbiguous(); } static TemplateArgumentLoc getTrivialIntegralTemplateArgument(Sema &S, SourceLocation Loc, QualType T, uint64_t I) { TemplateArgument Arg(S.Context, S.Context.MakeIntValue(I, T), T); return S.getTrivialTemplateArgumentLoc(Arg, T, Loc); } static TemplateArgumentLoc getTrivialTypeTemplateArgument(Sema &S, SourceLocation Loc, QualType T) { return S.getTrivialTemplateArgumentLoc(TemplateArgument(T), QualType(), Loc); } namespace { enum class IsTupleLike { TupleLike, NotTupleLike, Error }; } static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T, llvm::APSInt &Size) { EnterExpressionEvaluationContext ContextRAII( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); DeclarationName Value = S.PP.getIdentifierInfo("value"); LookupResult R(S, Value, Loc, Sema::LookupOrdinaryName); // Form template argument list for tuple_size. TemplateArgumentListInfo Args(Loc, Loc); Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T)); // If there's no tuple_size specialization, it's not tuple-like. if (lookupStdTypeTraitMember(S, R, Loc, "tuple_size", Args, /*DiagID*/0)) return IsTupleLike::NotTupleLike; // If we get this far, we've committed to the tuple interpretation, but // we can still fail if there actually isn't a usable ::value. struct ICEDiagnoser : Sema::VerifyICEDiagnoser { LookupResult &R; TemplateArgumentListInfo &Args; ICEDiagnoser(LookupResult &R, TemplateArgumentListInfo &Args) : R(R), Args(Args) {} void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) { S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant) << printTemplateArgs(S.Context.getPrintingPolicy(), Args); } } Diagnoser(R, Args); if (R.empty()) { Diagnoser.diagnoseNotICE(S, Loc, SourceRange()); return IsTupleLike::Error; } ExprResult E = S.BuildDeclarationNameExpr(CXXScopeSpec(), R, /*NeedsADL*/false); if (E.isInvalid()) return IsTupleLike::Error; E = S.VerifyIntegerConstantExpression(E.get(), &Size, Diagnoser, false); if (E.isInvalid()) return IsTupleLike::Error; return IsTupleLike::TupleLike; } /// \return std::tuple_element::type. static QualType getTupleLikeElementType(Sema &S, SourceLocation Loc, unsigned I, QualType T) { // Form template argument list for tuple_element. TemplateArgumentListInfo Args(Loc, Loc); Args.addArgument( getTrivialIntegralTemplateArgument(S, Loc, S.Context.getSizeType(), I)); Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T)); DeclarationName TypeDN = S.PP.getIdentifierInfo("type"); LookupResult R(S, TypeDN, Loc, Sema::LookupOrdinaryName); if (lookupStdTypeTraitMember( S, R, Loc, "tuple_element", Args, diag::err_decomp_decl_std_tuple_element_not_specialized)) return QualType(); auto *TD = R.getAsSingle(); if (!TD) { R.suppressDiagnostics(); S.Diag(Loc, diag::err_decomp_decl_std_tuple_element_not_specialized) << printTemplateArgs(S.Context.getPrintingPolicy(), Args); if (!R.empty()) S.Diag(R.getRepresentativeDecl()->getLocation(), diag::note_declared_at); return QualType(); } return S.Context.getTypeDeclType(TD); } namespace { struct BindingDiagnosticTrap { Sema &S; DiagnosticErrorTrap Trap; BindingDecl *BD; BindingDiagnosticTrap(Sema &S, BindingDecl *BD) : S(S), Trap(S.Diags), BD(BD) {} ~BindingDiagnosticTrap() { if (Trap.hasErrorOccurred()) S.Diag(BD->getLocation(), diag::note_in_binding_decl_init) << BD; } }; } static bool checkTupleLikeDecomposition(Sema &S, ArrayRef Bindings, VarDecl *Src, QualType DecompType, const llvm::APSInt &TupleSize) { if ((int64_t)Bindings.size() != TupleSize) { S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) << DecompType << (unsigned)Bindings.size() << TupleSize.toString(10) << (TupleSize < Bindings.size()); return true; } if (Bindings.empty()) return false; DeclarationName GetDN = S.PP.getIdentifierInfo("get"); // [dcl.decomp]p3: // The unqualified-id get is looked up in the scope of E by class member // access lookup LookupResult MemberGet(S, GetDN, Src->getLocation(), Sema::LookupMemberName); bool UseMemberGet = false; if (S.isCompleteType(Src->getLocation(), DecompType)) { if (auto *RD = DecompType->getAsCXXRecordDecl()) S.LookupQualifiedName(MemberGet, RD); if (MemberGet.isAmbiguous()) return true; UseMemberGet = !MemberGet.empty(); S.FilterAcceptableTemplateNames(MemberGet); } unsigned I = 0; for (auto *B : Bindings) { BindingDiagnosticTrap Trap(S, B); SourceLocation Loc = B->getLocation(); ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc); if (E.isInvalid()) return true; // e is an lvalue if the type of the entity is an lvalue reference and // an xvalue otherwise if (!Src->getType()->isLValueReferenceType()) E = ImplicitCastExpr::Create(S.Context, E.get()->getType(), CK_NoOp, E.get(), nullptr, VK_XValue); TemplateArgumentListInfo Args(Loc, Loc); Args.addArgument( getTrivialIntegralTemplateArgument(S, Loc, S.Context.getSizeType(), I)); if (UseMemberGet) { // if [lookup of member get] finds at least one declaration, the // initializer is e.get(). E = S.BuildMemberReferenceExpr(E.get(), DecompType, Loc, false, CXXScopeSpec(), SourceLocation(), nullptr, MemberGet, &Args, nullptr); if (E.isInvalid()) return true; E = S.ActOnCallExpr(nullptr, E.get(), Loc, None, Loc); } else { // Otherwise, the initializer is get(e), where get is looked up // in the associated namespaces. Expr *Get = UnresolvedLookupExpr::Create( S.Context, nullptr, NestedNameSpecifierLoc(), SourceLocation(), DeclarationNameInfo(GetDN, Loc), /*RequiresADL*/true, &Args, UnresolvedSetIterator(), UnresolvedSetIterator()); Expr *Arg = E.get(); E = S.ActOnCallExpr(nullptr, Get, Loc, Arg, Loc); } if (E.isInvalid()) return true; Expr *Init = E.get(); // Given the type T designated by std::tuple_element::type, QualType T = getTupleLikeElementType(S, Loc, I, DecompType); if (T.isNull()) return true; // each vi is a variable of type "reference to T" initialized with the // initializer, where the reference is an lvalue reference if the // initializer is an lvalue and an rvalue reference otherwise QualType RefType = S.BuildReferenceType(T, E.get()->isLValue(), Loc, B->getDeclName()); if (RefType.isNull()) return true; auto *RefVD = VarDecl::Create( S.Context, Src->getDeclContext(), Loc, Loc, B->getDeclName().getAsIdentifierInfo(), RefType, S.Context.getTrivialTypeSourceInfo(T, Loc), Src->getStorageClass()); RefVD->setLexicalDeclContext(Src->getLexicalDeclContext()); RefVD->setTSCSpec(Src->getTSCSpec()); RefVD->setImplicit(); if (Src->isInlineSpecified()) RefVD->setInlineSpecified(); RefVD->getLexicalDeclContext()->addHiddenDecl(RefVD); InitializedEntity Entity = InitializedEntity::InitializeBinding(RefVD); InitializationKind Kind = InitializationKind::CreateCopy(Loc, Loc); InitializationSequence Seq(S, Entity, Kind, Init); E = Seq.Perform(S, Entity, Kind, Init); if (E.isInvalid()) return true; E = S.ActOnFinishFullExpr(E.get(), Loc); if (E.isInvalid()) return true; RefVD->setInit(E.get()); RefVD->checkInitIsICE(); E = S.BuildDeclarationNameExpr(CXXScopeSpec(), DeclarationNameInfo(B->getDeclName(), Loc), RefVD); if (E.isInvalid()) return true; B->setBinding(T, E.get()); I++; } return false; } /// Find the base class to decompose in a built-in decomposition of a class type. /// This base class search is, unfortunately, not quite like any other that we /// perform anywhere else in C++. static const CXXRecordDecl *findDecomposableBaseClass(Sema &S, SourceLocation Loc, const CXXRecordDecl *RD, CXXCastPath &BasePath) { auto BaseHasFields = [](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { return Specifier->getType()->getAsCXXRecordDecl()->hasDirectFields(); }; const CXXRecordDecl *ClassWithFields = nullptr; if (RD->hasDirectFields()) // [dcl.decomp]p4: // Otherwise, all of E's non-static data members shall be public direct // members of E ... ClassWithFields = RD; else { // ... or of ... CXXBasePaths Paths; Paths.setOrigin(const_cast(RD)); if (!RD->lookupInBases(BaseHasFields, Paths)) { // If no classes have fields, just decompose RD itself. (This will work // if and only if zero bindings were provided.) return RD; } CXXBasePath *BestPath = nullptr; for (auto &P : Paths) { if (!BestPath) BestPath = &P; else if (!S.Context.hasSameType(P.back().Base->getType(), BestPath->back().Base->getType())) { // ... the same ... S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members) << false << RD << BestPath->back().Base->getType() << P.back().Base->getType(); return nullptr; } else if (P.Access < BestPath->Access) { BestPath = &P; } } // ... unambiguous ... QualType BaseType = BestPath->back().Base->getType(); if (Paths.isAmbiguous(S.Context.getCanonicalType(BaseType))) { S.Diag(Loc, diag::err_decomp_decl_ambiguous_base) << RD << BaseType << S.getAmbiguousPathsDisplayString(Paths); return nullptr; } // ... public base class of E. if (BestPath->Access != AS_public) { S.Diag(Loc, diag::err_decomp_decl_non_public_base) << RD << BaseType; for (auto &BS : *BestPath) { if (BS.Base->getAccessSpecifier() != AS_public) { S.Diag(BS.Base->getLocStart(), diag::note_access_constrained_by_path) << (BS.Base->getAccessSpecifier() == AS_protected) << (BS.Base->getAccessSpecifierAsWritten() == AS_none); break; } } return nullptr; } ClassWithFields = BaseType->getAsCXXRecordDecl(); S.BuildBasePathArray(Paths, BasePath); } // The above search did not check whether the selected class itself has base // classes with fields, so check that now. CXXBasePaths Paths; if (ClassWithFields->lookupInBases(BaseHasFields, Paths)) { S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members) << (ClassWithFields == RD) << RD << ClassWithFields << Paths.front().back().Base->getType(); return nullptr; } return ClassWithFields; } static bool checkMemberDecomposition(Sema &S, ArrayRef Bindings, ValueDecl *Src, QualType DecompType, const CXXRecordDecl *RD) { CXXCastPath BasePath; RD = findDecomposableBaseClass(S, Src->getLocation(), RD, BasePath); if (!RD) return true; QualType BaseType = S.Context.getQualifiedType(S.Context.getRecordType(RD), DecompType.getQualifiers()); auto DiagnoseBadNumberOfBindings = [&]() -> bool { unsigned NumFields = std::count_if(RD->field_begin(), RD->field_end(), [](FieldDecl *FD) { return !FD->isUnnamedBitfield(); }); assert(Bindings.size() != NumFields); S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) << DecompType << (unsigned)Bindings.size() << NumFields << (NumFields < Bindings.size()); return true; }; // all of E's non-static data members shall be public [...] members, // E shall not have an anonymous union member, ... unsigned I = 0; for (auto *FD : RD->fields()) { if (FD->isUnnamedBitfield()) continue; if (FD->isAnonymousStructOrUnion()) { S.Diag(Src->getLocation(), diag::err_decomp_decl_anon_union_member) << DecompType << FD->getType()->isUnionType(); S.Diag(FD->getLocation(), diag::note_declared_at); return true; } // We have a real field to bind. if (I >= Bindings.size()) return DiagnoseBadNumberOfBindings(); auto *B = Bindings[I++]; SourceLocation Loc = B->getLocation(); if (FD->getAccess() != AS_public) { S.Diag(Loc, diag::err_decomp_decl_non_public_member) << FD << DecompType; // Determine whether the access specifier was explicit. bool Implicit = true; for (const auto *D : RD->decls()) { if (declaresSameEntity(D, FD)) break; if (isa(D)) { Implicit = false; break; } } S.Diag(FD->getLocation(), diag::note_access_natural) << (FD->getAccess() == AS_protected) << Implicit; return true; } // Initialize the binding to Src.FD. ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc); if (E.isInvalid()) return true; E = S.ImpCastExprToType(E.get(), BaseType, CK_UncheckedDerivedToBase, VK_LValue, &BasePath); if (E.isInvalid()) return true; E = S.BuildFieldReferenceExpr(E.get(), /*IsArrow*/ false, Loc, CXXScopeSpec(), FD, DeclAccessPair::make(FD, FD->getAccess()), DeclarationNameInfo(FD->getDeclName(), Loc)); if (E.isInvalid()) return true; // If the type of the member is T, the referenced type is cv T, where cv is // the cv-qualification of the decomposition expression. // // FIXME: We resolve a defect here: if the field is mutable, we do not add // 'const' to the type of the field. Qualifiers Q = DecompType.getQualifiers(); if (FD->isMutable()) Q.removeConst(); B->setBinding(S.BuildQualifiedType(FD->getType(), Loc, Q), E.get()); } if (I != Bindings.size()) return DiagnoseBadNumberOfBindings(); return false; } void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) { QualType DecompType = DD->getType(); // If the type of the decomposition is dependent, then so is the type of // each binding. if (DecompType->isDependentType()) { for (auto *B : DD->bindings()) B->setType(Context.DependentTy); return; } DecompType = DecompType.getNonReferenceType(); ArrayRef Bindings = DD->bindings(); // C++1z [dcl.decomp]/2: // If E is an array type [...] // As an extension, we also support decomposition of built-in complex and // vector types. if (auto *CAT = Context.getAsConstantArrayType(DecompType)) { if (checkArrayDecomposition(*this, Bindings, DD, DecompType, CAT)) DD->setInvalidDecl(); return; } if (auto *VT = DecompType->getAs()) { if (checkVectorDecomposition(*this, Bindings, DD, DecompType, VT)) DD->setInvalidDecl(); return; } if (auto *CT = DecompType->getAs()) { if (checkComplexDecomposition(*this, Bindings, DD, DecompType, CT)) DD->setInvalidDecl(); return; } // C++1z [dcl.decomp]/3: // if the expression std::tuple_size::value is a well-formed integral // constant expression, [...] llvm::APSInt TupleSize(32); switch (isTupleLike(*this, DD->getLocation(), DecompType, TupleSize)) { case IsTupleLike::Error: DD->setInvalidDecl(); return; case IsTupleLike::TupleLike: if (checkTupleLikeDecomposition(*this, Bindings, DD, DecompType, TupleSize)) DD->setInvalidDecl(); return; case IsTupleLike::NotTupleLike: break; } // C++1z [dcl.dcl]/8: // [E shall be of array or non-union class type] CXXRecordDecl *RD = DecompType->getAsCXXRecordDecl(); if (!RD || RD->isUnion()) { Diag(DD->getLocation(), diag::err_decomp_decl_unbindable_type) << DD << !RD << DecompType; DD->setInvalidDecl(); return; } // C++1z [dcl.decomp]/4: // all of E's non-static data members shall be [...] direct members of // E or of the same unambiguous public base class of E, ... if (checkMemberDecomposition(*this, Bindings, DD, DecompType, RD)) DD->setInvalidDecl(); } /// \brief Merge the exception specifications of two variable declarations. /// /// This is called when there's a redeclaration of a VarDecl. The function /// checks if the redeclaration might have an exception specification and /// validates compatibility and merges the specs if necessary. void Sema::MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old) { // Shortcut if exceptions are disabled. if (!getLangOpts().CXXExceptions) return; assert(Context.hasSameType(New->getType(), Old->getType()) && "Should only be called if types are otherwise the same."); QualType NewType = New->getType(); QualType OldType = Old->getType(); // We're only interested in pointers and references to functions, as well // as pointers to member functions. if (const ReferenceType *R = NewType->getAs()) { NewType = R->getPointeeType(); OldType = OldType->getAs()->getPointeeType(); } else if (const PointerType *P = NewType->getAs()) { NewType = P->getPointeeType(); OldType = OldType->getAs()->getPointeeType(); } else if (const MemberPointerType *M = NewType->getAs()) { NewType = M->getPointeeType(); OldType = OldType->getAs()->getPointeeType(); } if (!NewType->isFunctionProtoType()) return; // There's lots of special cases for functions. For function pointers, system // libraries are hopefully not as broken so that we don't need these // workarounds. if (CheckEquivalentExceptionSpec( OldType->getAs(), Old->getLocation(), NewType->getAs(), New->getLocation())) { New->setInvalidDecl(); } } /// CheckCXXDefaultArguments - Verify that the default arguments for a /// function declaration are well-formed according to C++ /// [dcl.fct.default]. void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { unsigned NumParams = FD->getNumParams(); unsigned p; // Find first parameter with a default argument for (p = 0; p < NumParams; ++p) { ParmVarDecl *Param = FD->getParamDecl(p); if (Param->hasDefaultArg()) break; } // C++11 [dcl.fct.default]p4: // In a given function declaration, each parameter subsequent to a parameter // with a default argument shall have a default argument supplied in this or // a previous declaration or shall be a function parameter pack. A default // argument shall not be redefined by a later declaration (not even to the // same value). unsigned LastMissingDefaultArg = 0; for (; p < NumParams; ++p) { ParmVarDecl *Param = FD->getParamDecl(p); if (!Param->hasDefaultArg() && !Param->isParameterPack()) { if (Param->isInvalidDecl()) /* We already complained about this parameter. */; else if (Param->getIdentifier()) Diag(Param->getLocation(), diag::err_param_default_argument_missing_name) << Param->getIdentifier(); else Diag(Param->getLocation(), diag::err_param_default_argument_missing); LastMissingDefaultArg = p; } } if (LastMissingDefaultArg > 0) { // Some default arguments were missing. Clear out all of the // default arguments up to (and including) the last missing // default argument, so that we leave the function parameters // in a semantically valid state. for (p = 0; p <= LastMissingDefaultArg; ++p) { ParmVarDecl *Param = FD->getParamDecl(p); if (Param->hasDefaultArg()) { Param->setDefaultArg(nullptr); } } } } // CheckConstexprParameterTypes - Check whether a function's parameter types // are all literal types. If so, return true. If not, produce a suitable // diagnostic and return false. static bool CheckConstexprParameterTypes(Sema &SemaRef, const FunctionDecl *FD) { unsigned ArgIndex = 0; const FunctionProtoType *FT = FD->getType()->getAs(); for (FunctionProtoType::param_type_iterator i = FT->param_type_begin(), e = FT->param_type_end(); i != e; ++i, ++ArgIndex) { const ParmVarDecl *PD = FD->getParamDecl(ArgIndex); SourceLocation ParamLoc = PD->getLocation(); if (!(*i)->isDependentType() && SemaRef.RequireLiteralType(ParamLoc, *i, diag::err_constexpr_non_literal_param, ArgIndex+1, PD->getSourceRange(), isa(FD))) return false; } return true; } /// \brief Get diagnostic %select index for tag kind for /// record diagnostic message. /// WARNING: Indexes apply to particular diagnostics only! /// /// \returns diagnostic %select index. static unsigned getRecordDiagFromTagKind(TagTypeKind Tag) { switch (Tag) { case TTK_Struct: return 0; case TTK_Interface: return 1; case TTK_Class: return 2; default: llvm_unreachable("Invalid tag kind for record diagnostic!"); } } // CheckConstexprFunctionDecl - Check whether a function declaration satisfies // the requirements of a constexpr function definition or a constexpr // constructor definition. If so, return true. If not, produce appropriate // diagnostics and return false. // // This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360. bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) { const CXXMethodDecl *MD = dyn_cast(NewFD); if (MD && MD->isInstance()) { // C++11 [dcl.constexpr]p4: // The definition of a constexpr constructor shall satisfy the following // constraints: // - the class shall not have any virtual base classes; const CXXRecordDecl *RD = MD->getParent(); if (RD->getNumVBases()) { Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base) << isa(NewFD) << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases(); for (const auto &I : RD->vbases()) Diag(I.getLocStart(), diag::note_constexpr_virtual_base_here) << I.getSourceRange(); return false; } } if (!isa(NewFD)) { // C++11 [dcl.constexpr]p3: // The definition of a constexpr function shall satisfy the following // constraints: // - it shall not be virtual; const CXXMethodDecl *Method = dyn_cast(NewFD); if (Method && Method->isVirtual()) { Method = Method->getCanonicalDecl(); Diag(Method->getLocation(), diag::err_constexpr_virtual); // If it's not obvious why this function is virtual, find an overridden // function which uses the 'virtual' keyword. const CXXMethodDecl *WrittenVirtual = Method; while (!WrittenVirtual->isVirtualAsWritten()) WrittenVirtual = *WrittenVirtual->begin_overridden_methods(); if (WrittenVirtual != Method) Diag(WrittenVirtual->getLocation(), diag::note_overridden_virtual_function); return false; } // - its return type shall be a literal type; QualType RT = NewFD->getReturnType(); if (!RT->isDependentType() && RequireLiteralType(NewFD->getLocation(), RT, diag::err_constexpr_non_literal_return)) return false; } // - each of its parameter types shall be a literal type; if (!CheckConstexprParameterTypes(*this, NewFD)) return false; return true; } /// Check the given declaration statement is legal within a constexpr function /// body. C++11 [dcl.constexpr]p3,p4, and C++1y [dcl.constexpr]p3. /// /// \return true if the body is OK (maybe only as an extension), false if we /// have diagnosed a problem. static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, DeclStmt *DS, SourceLocation &Cxx1yLoc) { // C++11 [dcl.constexpr]p3 and p4: // The definition of a constexpr function(p3) or constructor(p4) [...] shall // contain only for (const auto *DclIt : DS->decls()) { switch (DclIt->getKind()) { case Decl::StaticAssert: case Decl::Using: case Decl::UsingShadow: case Decl::UsingDirective: case Decl::UnresolvedUsingTypename: case Decl::UnresolvedUsingValue: // - static_assert-declarations // - using-declarations, // - using-directives, continue; case Decl::Typedef: case Decl::TypeAlias: { // - typedef declarations and alias-declarations that do not define // classes or enumerations, const auto *TN = cast(DclIt); if (TN->getUnderlyingType()->isVariablyModifiedType()) { // Don't allow variably-modified types in constexpr functions. TypeLoc TL = TN->getTypeSourceInfo()->getTypeLoc(); SemaRef.Diag(TL.getBeginLoc(), diag::err_constexpr_vla) << TL.getSourceRange() << TL.getType() << isa(Dcl); return false; } continue; } case Decl::Enum: case Decl::CXXRecord: // C++1y allows types to be defined, not just declared. if (cast(DclIt)->isThisDeclarationADefinition()) SemaRef.Diag(DS->getLocStart(), SemaRef.getLangOpts().CPlusPlus14 ? diag::warn_cxx11_compat_constexpr_type_definition : diag::ext_constexpr_type_definition) << isa(Dcl); continue; case Decl::EnumConstant: case Decl::IndirectField: case Decl::ParmVar: // These can only appear with other declarations which are banned in // C++11 and permitted in C++1y, so ignore them. continue; case Decl::Var: case Decl::Decomposition: { // C++1y [dcl.constexpr]p3 allows anything except: // a definition of a variable of non-literal type or of static or // thread storage duration or for which no initialization is performed. const auto *VD = cast(DclIt); if (VD->isThisDeclarationADefinition()) { if (VD->isStaticLocal()) { SemaRef.Diag(VD->getLocation(), diag::err_constexpr_local_var_static) << isa(Dcl) << (VD->getTLSKind() == VarDecl::TLS_Dynamic); return false; } if (!VD->getType()->isDependentType() && SemaRef.RequireLiteralType( VD->getLocation(), VD->getType(), diag::err_constexpr_local_var_non_literal_type, isa(Dcl))) return false; if (!VD->getType()->isDependentType() && !VD->hasInit() && !VD->isCXXForRangeDecl()) { SemaRef.Diag(VD->getLocation(), diag::err_constexpr_local_var_no_init) << isa(Dcl); return false; } } SemaRef.Diag(VD->getLocation(), SemaRef.getLangOpts().CPlusPlus14 ? diag::warn_cxx11_compat_constexpr_local_var : diag::ext_constexpr_local_var) << isa(Dcl); continue; } case Decl::NamespaceAlias: case Decl::Function: // These are disallowed in C++11 and permitted in C++1y. Allow them // everywhere as an extension. if (!Cxx1yLoc.isValid()) Cxx1yLoc = DS->getLocStart(); continue; default: SemaRef.Diag(DS->getLocStart(), diag::err_constexpr_body_invalid_stmt) << isa(Dcl); return false; } } return true; } /// Check that the given field is initialized within a constexpr constructor. /// /// \param Dcl The constexpr constructor being checked. /// \param Field The field being checked. This may be a member of an anonymous /// struct or union nested within the class being checked. /// \param Inits All declarations, including anonymous struct/union members and /// indirect members, for which any initialization was provided. /// \param Diagnosed Set to true if an error is produced. static void CheckConstexprCtorInitializer(Sema &SemaRef, const FunctionDecl *Dcl, FieldDecl *Field, llvm::SmallSet &Inits, bool &Diagnosed) { if (Field->isInvalidDecl()) return; if (Field->isUnnamedBitfield()) return; // Anonymous unions with no variant members and empty anonymous structs do not // need to be explicitly initialized. FIXME: Anonymous structs that contain no // indirect fields don't need initializing. if (Field->isAnonymousStructOrUnion() && (Field->getType()->isUnionType() ? !Field->getType()->getAsCXXRecordDecl()->hasVariantMembers() : Field->getType()->getAsCXXRecordDecl()->isEmpty())) return; if (!Inits.count(Field)) { if (!Diagnosed) { SemaRef.Diag(Dcl->getLocation(), diag::err_constexpr_ctor_missing_init); Diagnosed = true; } SemaRef.Diag(Field->getLocation(), diag::note_constexpr_ctor_missing_init); } else if (Field->isAnonymousStructOrUnion()) { const RecordDecl *RD = Field->getType()->castAs()->getDecl(); for (auto *I : RD->fields()) // If an anonymous union contains an anonymous struct of which any member // is initialized, all members must be initialized. if (!RD->isUnion() || Inits.count(I)) CheckConstexprCtorInitializer(SemaRef, Dcl, I, Inits, Diagnosed); } } /// Check the provided statement is allowed in a constexpr function /// definition. static bool CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S, SmallVectorImpl &ReturnStmts, SourceLocation &Cxx1yLoc) { // - its function-body shall be [...] a compound-statement that contains only switch (S->getStmtClass()) { case Stmt::NullStmtClass: // - null statements, return true; case Stmt::DeclStmtClass: // - static_assert-declarations // - using-declarations, // - using-directives, // - typedef declarations and alias-declarations that do not define // classes or enumerations, if (!CheckConstexprDeclStmt(SemaRef, Dcl, cast(S), Cxx1yLoc)) return false; return true; case Stmt::ReturnStmtClass: // - and exactly one return statement; if (isa(Dcl)) { // C++1y allows return statements in constexpr constructors. if (!Cxx1yLoc.isValid()) Cxx1yLoc = S->getLocStart(); return true; } ReturnStmts.push_back(S->getLocStart()); return true; case Stmt::CompoundStmtClass: { // C++1y allows compound-statements. if (!Cxx1yLoc.isValid()) Cxx1yLoc = S->getLocStart(); CompoundStmt *CompStmt = cast(S); for (auto *BodyIt : CompStmt->body()) { if (!CheckConstexprFunctionStmt(SemaRef, Dcl, BodyIt, ReturnStmts, Cxx1yLoc)) return false; } return true; } case Stmt::AttributedStmtClass: if (!Cxx1yLoc.isValid()) Cxx1yLoc = S->getLocStart(); return true; case Stmt::IfStmtClass: { // C++1y allows if-statements. if (!Cxx1yLoc.isValid()) Cxx1yLoc = S->getLocStart(); IfStmt *If = cast(S); if (!CheckConstexprFunctionStmt(SemaRef, Dcl, If->getThen(), ReturnStmts, Cxx1yLoc)) return false; if (If->getElse() && !CheckConstexprFunctionStmt(SemaRef, Dcl, If->getElse(), ReturnStmts, Cxx1yLoc)) return false; return true; } case Stmt::WhileStmtClass: case Stmt::DoStmtClass: case Stmt::ForStmtClass: case Stmt::CXXForRangeStmtClass: case Stmt::ContinueStmtClass: // C++1y allows all of these. We don't allow them as extensions in C++11, // because they don't make sense without variable mutation. if (!SemaRef.getLangOpts().CPlusPlus14) break; if (!Cxx1yLoc.isValid()) Cxx1yLoc = S->getLocStart(); for (Stmt *SubStmt : S->children()) if (SubStmt && !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts, Cxx1yLoc)) return false; return true; case Stmt::SwitchStmtClass: case Stmt::CaseStmtClass: case Stmt::DefaultStmtClass: case Stmt::BreakStmtClass: // C++1y allows switch-statements, and since they don't need variable // mutation, we can reasonably allow them in C++11 as an extension. if (!Cxx1yLoc.isValid()) Cxx1yLoc = S->getLocStart(); for (Stmt *SubStmt : S->children()) if (SubStmt && !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts, Cxx1yLoc)) return false; return true; default: if (!isa(S)) break; // C++1y allows expression-statements. if (!Cxx1yLoc.isValid()) Cxx1yLoc = S->getLocStart(); return true; } SemaRef.Diag(S->getLocStart(), diag::err_constexpr_body_invalid_stmt) << isa(Dcl); return false; } /// Check the body for the given constexpr function declaration only contains /// the permitted types of statement. C++11 [dcl.constexpr]p3,p4. /// /// \return true if the body is OK, false if we have diagnosed a problem. bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { if (isa(Body)) { // C++11 [dcl.constexpr]p3: // The definition of a constexpr function shall satisfy the following // constraints: [...] // - its function-body shall be = delete, = default, or a // compound-statement // // C++11 [dcl.constexpr]p4: // In the definition of a constexpr constructor, [...] // - its function-body shall not be a function-try-block; Diag(Body->getLocStart(), diag::err_constexpr_function_try_block) << isa(Dcl); return false; } SmallVector ReturnStmts; // - its function-body shall be [...] a compound-statement that contains only // [... list of cases ...] CompoundStmt *CompBody = cast(Body); SourceLocation Cxx1yLoc; for (auto *BodyIt : CompBody->body()) { if (!CheckConstexprFunctionStmt(*this, Dcl, BodyIt, ReturnStmts, Cxx1yLoc)) return false; } if (Cxx1yLoc.isValid()) Diag(Cxx1yLoc, getLangOpts().CPlusPlus14 ? diag::warn_cxx11_compat_constexpr_body_invalid_stmt : diag::ext_constexpr_body_invalid_stmt) << isa(Dcl); if (const CXXConstructorDecl *Constructor = dyn_cast(Dcl)) { const CXXRecordDecl *RD = Constructor->getParent(); // DR1359: // - every non-variant non-static data member and base class sub-object // shall be initialized; // DR1460: // - if the class is a union having variant members, exactly one of them // shall be initialized; if (RD->isUnion()) { if (Constructor->getNumCtorInitializers() == 0 && RD->hasVariantMembers()) { Diag(Dcl->getLocation(), diag::err_constexpr_union_ctor_no_init); return false; } } else if (!Constructor->isDependentContext() && !Constructor->isDelegatingConstructor()) { assert(RD->getNumVBases() == 0 && "constexpr ctor with virtual bases"); // Skip detailed checking if we have enough initializers, and we would // allow at most one initializer per member. bool AnyAnonStructUnionMembers = false; unsigned Fields = 0; for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); I != E; ++I, ++Fields) { if (I->isAnonymousStructOrUnion()) { AnyAnonStructUnionMembers = true; break; } } // DR1460: // - if the class is a union-like class, but is not a union, for each of // its anonymous union members having variant members, exactly one of // them shall be initialized; if (AnyAnonStructUnionMembers || Constructor->getNumCtorInitializers() != RD->getNumBases() + Fields) { // Check initialization of non-static data members. Base classes are // always initialized so do not need to be checked. Dependent bases // might not have initializers in the member initializer list. llvm::SmallSet Inits; for (const auto *I: Constructor->inits()) { if (FieldDecl *FD = I->getMember()) Inits.insert(FD); else if (IndirectFieldDecl *ID = I->getIndirectMember()) Inits.insert(ID->chain_begin(), ID->chain_end()); } bool Diagnosed = false; for (auto *I : RD->fields()) CheckConstexprCtorInitializer(*this, Dcl, I, Inits, Diagnosed); if (Diagnosed) return false; } } } else { if (ReturnStmts.empty()) { // C++1y doesn't require constexpr functions to contain a 'return' // statement. We still do, unless the return type might be void, because // otherwise if there's no return statement, the function cannot // be used in a core constant expression. bool OK = getLangOpts().CPlusPlus14 && (Dcl->getReturnType()->isVoidType() || Dcl->getReturnType()->isDependentType()); Diag(Dcl->getLocation(), OK ? diag::warn_cxx11_compat_constexpr_body_no_return : diag::err_constexpr_body_no_return); if (!OK) return false; } else if (ReturnStmts.size() > 1) { Diag(ReturnStmts.back(), getLangOpts().CPlusPlus14 ? diag::warn_cxx11_compat_constexpr_body_multiple_return : diag::ext_constexpr_body_multiple_return); for (unsigned I = 0; I < ReturnStmts.size() - 1; ++I) Diag(ReturnStmts[I], diag::note_constexpr_body_previous_return); } } // C++11 [dcl.constexpr]p5: // if no function argument values exist such that the function invocation // substitution would produce a constant expression, the program is // ill-formed; no diagnostic required. // C++11 [dcl.constexpr]p3: // - every constructor call and implicit conversion used in initializing the // return value shall be one of those allowed in a constant expression. // C++11 [dcl.constexpr]p4: // - every constructor involved in initializing non-static data members and // base class sub-objects shall be a constexpr constructor. SmallVector Diags; if (!Expr::isPotentialConstantExpr(Dcl, Diags)) { Diag(Dcl->getLocation(), diag::ext_constexpr_function_never_constant_expr) << isa(Dcl); for (size_t I = 0, N = Diags.size(); I != N; ++I) Diag(Diags[I].first, Diags[I].second); // Don't return false here: we allow this for compatibility in // system headers. } return true; } /// isCurrentClassName - Determine whether the identifier II is the /// name of the class type currently being defined. In the case of /// nested classes, this will only return true if II is the name of /// the innermost class. bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, const CXXScopeSpec *SS) { assert(getLangOpts().CPlusPlus && "No class names in C!"); CXXRecordDecl *CurDecl; if (SS && SS->isSet() && !SS->isInvalid()) { DeclContext *DC = computeDeclContext(*SS, true); CurDecl = dyn_cast_or_null(DC); } else CurDecl = dyn_cast_or_null(CurContext); if (CurDecl && CurDecl->getIdentifier()) return &II == CurDecl->getIdentifier(); return false; } /// \brief Determine whether the identifier II is a typo for the name of /// the class type currently being defined. If so, update it to the identifier /// that should have been used. bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) { assert(getLangOpts().CPlusPlus && "No class names in C!"); if (!getLangOpts().SpellChecking) return false; CXXRecordDecl *CurDecl; if (SS && SS->isSet() && !SS->isInvalid()) { DeclContext *DC = computeDeclContext(*SS, true); CurDecl = dyn_cast_or_null(DC); } else CurDecl = dyn_cast_or_null(CurContext); if (CurDecl && CurDecl->getIdentifier() && II != CurDecl->getIdentifier() && 3 * II->getName().edit_distance(CurDecl->getIdentifier()->getName()) < II->getLength()) { II = CurDecl->getIdentifier(); return true; } return false; } /// \brief Determine whether the given class is a base class of the given /// class, including looking at dependent bases. static bool findCircularInheritance(const CXXRecordDecl *Class, const CXXRecordDecl *Current) { SmallVector Queue; Class = Class->getCanonicalDecl(); while (true) { for (const auto &I : Current->bases()) { CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl(); if (!Base) continue; Base = Base->getDefinition(); if (!Base) continue; if (Base->getCanonicalDecl() == Class) return true; Queue.push_back(Base); } if (Queue.empty()) return false; Current = Queue.pop_back_val(); } return false; } /// \brief Check the validity of a C++ base class specifier. /// /// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics /// and returns NULL otherwise. CXXBaseSpecifier * Sema::CheckBaseSpecifier(CXXRecordDecl *Class, SourceRange SpecifierRange, bool Virtual, AccessSpecifier Access, TypeSourceInfo *TInfo, SourceLocation EllipsisLoc) { QualType BaseType = TInfo->getType(); // C++ [class.union]p1: // A union shall not have base classes. if (Class->isUnion()) { Diag(Class->getLocation(), diag::err_base_clause_on_union) << SpecifierRange; return nullptr; } if (EllipsisLoc.isValid() && !TInfo->getType()->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << TInfo->getTypeLoc().getSourceRange(); EllipsisLoc = SourceLocation(); } SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); if (BaseType->isDependentType()) { // Make sure that we don't have circular inheritance among our dependent // bases. For non-dependent bases, the check for completeness below handles // this. if (CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl()) { if (BaseDecl->getCanonicalDecl() == Class->getCanonicalDecl() || ((BaseDecl = BaseDecl->getDefinition()) && findCircularInheritance(Class, BaseDecl))) { Diag(BaseLoc, diag::err_circular_inheritance) << BaseType << Context.getTypeDeclType(Class); if (BaseDecl->getCanonicalDecl() != Class->getCanonicalDecl()) Diag(BaseDecl->getLocation(), diag::note_previous_decl) << BaseType; return nullptr; } } return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, Class->getTagKind() == TTK_Class, Access, TInfo, EllipsisLoc); } // Base specifiers must be record types. if (!BaseType->isRecordType()) { Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; return nullptr; } // C++ [class.union]p1: // A union shall not be used as a base class. if (BaseType->isUnionType()) { Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; return nullptr; } // For the MS ABI, propagate DLL attributes to base class templates. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { if (Attr *ClassAttr = getDLLAttr(Class)) { if (auto *BaseTemplate = dyn_cast_or_null( BaseType->getAsCXXRecordDecl())) { propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseTemplate, BaseLoc); } } } // C++ [class.derived]p2: // The class-name in a base-specifier shall not be an incompletely // defined class. if (RequireCompleteType(BaseLoc, BaseType, diag::err_incomplete_base_class, SpecifierRange)) { Class->setInvalidDecl(); return nullptr; } // If the base class is polymorphic or isn't empty, the new one is/isn't, too. RecordDecl *BaseDecl = BaseType->getAs()->getDecl(); assert(BaseDecl && "Record type has no declaration"); BaseDecl = BaseDecl->getDefinition(); assert(BaseDecl && "Base type is not incomplete, but has no definition"); CXXRecordDecl *CXXBaseDecl = cast(BaseDecl); assert(CXXBaseDecl && "Base type is not a C++ type"); // A class which contains a flexible array member is not suitable for use as a // base class: // - If the layout determines that a base comes before another base, // the flexible array member would index into the subsequent base. // - If the layout determines that base comes before the derived class, // the flexible array member would index into the derived class. if (CXXBaseDecl->hasFlexibleArrayMember()) { Diag(BaseLoc, diag::err_base_class_has_flexible_array_member) << CXXBaseDecl->getDeclName(); return nullptr; } // C++ [class]p3: // If a class is marked final and it appears as a base-type-specifier in // base-clause, the program is ill-formed. if (FinalAttr *FA = CXXBaseDecl->getAttr()) { Diag(BaseLoc, diag::err_class_marked_final_used_as_base) << CXXBaseDecl->getDeclName() << FA->isSpelledAsSealed(); Diag(CXXBaseDecl->getLocation(), diag::note_entity_declared_at) << CXXBaseDecl->getDeclName() << FA->getRange(); return nullptr; } if (BaseDecl->isInvalidDecl()) Class->setInvalidDecl(); // Create the base specifier. return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, Class->getTagKind() == TTK_Class, Access, TInfo, EllipsisLoc); } /// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is /// one entry in the base class list of a class specifier, for /// example: /// class foo : public bar, virtual private baz { /// 'public bar' and 'virtual private baz' are each base-specifiers. BaseResult Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, ParsedAttributes &Attributes, bool Virtual, AccessSpecifier Access, ParsedType basetype, SourceLocation BaseLoc, SourceLocation EllipsisLoc) { if (!classdecl) return true; AdjustDeclIfTemplate(classdecl); CXXRecordDecl *Class = dyn_cast(classdecl); if (!Class) return true; // We haven't yet attached the base specifiers. Class->setIsParsingBaseSpecifiers(); // We do not support any C++11 attributes on base-specifiers yet. // Diagnose any attributes we see. if (!Attributes.empty()) { for (AttributeList *Attr = Attributes.getList(); Attr; Attr = Attr->getNext()) { if (Attr->isInvalid() || Attr->getKind() == AttributeList::IgnoredAttribute) continue; Diag(Attr->getLoc(), Attr->getKind() == AttributeList::UnknownAttribute ? diag::warn_unknown_attribute_ignored : diag::err_base_specifier_attribute) << Attr->getName(); } } TypeSourceInfo *TInfo = nullptr; GetTypeFromParser(basetype, &TInfo); if (EllipsisLoc.isInvalid() && DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo, UPPC_BaseType)) return true; if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange, Virtual, Access, TInfo, EllipsisLoc)) return BaseSpec; else Class->setInvalidDecl(); return true; } /// Use small set to collect indirect bases. As this is only used /// locally, there's no need to abstract the small size parameter. typedef llvm::SmallPtrSet IndirectBaseSet; /// \brief Recursively add the bases of Type. Don't add Type itself. static void NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set, const QualType &Type) { // Even though the incoming type is a base, it might not be // a class -- it could be a template parm, for instance. if (auto Rec = Type->getAs()) { auto Decl = Rec->getAsCXXRecordDecl(); // Iterate over its bases. for (const auto &BaseSpec : Decl->bases()) { QualType Base = Context.getCanonicalType(BaseSpec.getType()) .getUnqualifiedType(); if (Set.insert(Base).second) // If we've not already seen it, recurse. NoteIndirectBases(Context, Set, Base); } } } /// \brief Performs the actual work of attaching the given base class /// specifiers to a C++ class. bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, MutableArrayRef Bases) { if (Bases.empty()) return false; // Used to keep track of which base types we have already seen, so // that we can properly diagnose redundant direct base types. Note // that the key is always the unqualified canonical type of the base // class. std::map KnownBaseTypes; // Used to track indirect bases so we can see if a direct base is // ambiguous. IndirectBaseSet IndirectBaseTypes; // Copy non-redundant base specifiers into permanent storage. unsigned NumGoodBases = 0; bool Invalid = false; for (unsigned idx = 0; idx < Bases.size(); ++idx) { QualType NewBaseType = Context.getCanonicalType(Bases[idx]->getType()); NewBaseType = NewBaseType.getLocalUnqualifiedType(); CXXBaseSpecifier *&KnownBase = KnownBaseTypes[NewBaseType]; if (KnownBase) { // C++ [class.mi]p3: // A class shall not be specified as a direct base class of a // derived class more than once. Diag(Bases[idx]->getLocStart(), diag::err_duplicate_base_class) << KnownBase->getType() << Bases[idx]->getSourceRange(); // Delete the duplicate base class specifier; we're going to // overwrite its pointer later. Context.Deallocate(Bases[idx]); Invalid = true; } else { // Okay, add this new base class. KnownBase = Bases[idx]; Bases[NumGoodBases++] = Bases[idx]; // Note this base's direct & indirect bases, if there could be ambiguity. if (Bases.size() > 1) NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType); if (const RecordType *Record = NewBaseType->getAs()) { const CXXRecordDecl *RD = cast(Record->getDecl()); if (Class->isInterface() && (!RD->isInterface() || KnownBase->getAccessSpecifier() != AS_public)) { // The Microsoft extension __interface does not permit bases that // are not themselves public interfaces. Diag(KnownBase->getLocStart(), diag::err_invalid_base_in_interface) << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getName() << RD->getSourceRange(); Invalid = true; } if (RD->hasAttr()) Class->addAttr(WeakAttr::CreateImplicit(Context)); } } } // Attach the remaining base class specifiers to the derived class. Class->setBases(Bases.data(), NumGoodBases); for (unsigned idx = 0; idx < NumGoodBases; ++idx) { // Check whether this direct base is inaccessible due to ambiguity. QualType BaseType = Bases[idx]->getType(); CanQualType CanonicalBase = Context.getCanonicalType(BaseType) .getUnqualifiedType(); if (IndirectBaseTypes.count(CanonicalBase)) { CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/true); bool found = Class->isDerivedFrom(CanonicalBase->getAsCXXRecordDecl(), Paths); assert(found); (void)found; if (Paths.isAmbiguous(CanonicalBase)) Diag(Bases[idx]->getLocStart (), diag::warn_inaccessible_base_class) << BaseType << getAmbiguousPathsDisplayString(Paths) << Bases[idx]->getSourceRange(); else assert(Bases[idx]->isVirtual()); } // Delete the base class specifier, since its data has been copied // into the CXXRecordDecl. Context.Deallocate(Bases[idx]); } return Invalid; } /// ActOnBaseSpecifiers - Attach the given base specifiers to the /// class, after checking whether there are any duplicate base /// classes. void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, MutableArrayRef Bases) { if (!ClassDecl || Bases.empty()) return; AdjustDeclIfTemplate(ClassDecl); AttachBaseSpecifiers(cast(ClassDecl), Bases); } /// \brief Determine whether the type \p Derived is a C++ class that is /// derived from the type \p Base. bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) { if (!getLangOpts().CPlusPlus) return false; CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl(); if (!DerivedRD) return false; CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl(); if (!BaseRD) return false; // If either the base or the derived type is invalid, don't try to // check whether one is derived from the other. if (BaseRD->isInvalidDecl() || DerivedRD->isInvalidDecl()) return false; // FIXME: In a modules build, do we need the entire path to be visible for us // to be able to use the inheritance relationship? if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined()) return false; return DerivedRD->isDerivedFrom(BaseRD); } /// \brief Determine whether the type \p Derived is a C++ class that is /// derived from the type \p Base. bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base, CXXBasePaths &Paths) { if (!getLangOpts().CPlusPlus) return false; CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl(); if (!DerivedRD) return false; CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl(); if (!BaseRD) return false; if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined()) return false; return DerivedRD->isDerivedFrom(BaseRD, Paths); } void Sema::BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePathArray) { assert(BasePathArray.empty() && "Base path array must be empty!"); assert(Paths.isRecordingPaths() && "Must record paths!"); const CXXBasePath &Path = Paths.front(); // We first go backward and check if we have a virtual base. // FIXME: It would be better if CXXBasePath had the base specifier for // the nearest virtual base. unsigned Start = 0; for (unsigned I = Path.size(); I != 0; --I) { if (Path[I - 1].Base->isVirtual()) { Start = I - 1; break; } } // Now add all bases. for (unsigned I = Start, E = Path.size(); I != E; ++I) BasePathArray.push_back(const_cast(Path[I].Base)); } /// CheckDerivedToBaseConversion - Check whether the Derived-to-Base /// conversion (where Derived and Base are class types) is /// well-formed, meaning that the conversion is unambiguous (and /// that all of the base classes are accessible). Returns true /// and emits a diagnostic if the code is ill-formed, returns false /// otherwise. Loc is the location where this routine should point to /// if there is an error, and Range is the source range to highlight /// if there is an error. /// /// If either InaccessibleBaseID or AmbigiousBaseConvID are 0, then the /// diagnostic for the respective type of error will be suppressed, but the /// check for ill-formed code will still be performed. bool Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, unsigned InaccessibleBaseID, unsigned AmbigiousBaseConvID, SourceLocation Loc, SourceRange Range, DeclarationName Name, CXXCastPath *BasePath, bool IgnoreAccess) { // First, determine whether the path from Derived to Base is // ambiguous. This is slightly more expensive than checking whether // the Derived to Base conversion exists, because here we need to // explore multiple paths to determine if there is an ambiguity. CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/false); bool DerivationOkay = IsDerivedFrom(Loc, Derived, Base, Paths); assert(DerivationOkay && "Can only be used with a derived-to-base conversion"); (void)DerivationOkay; if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) { if (!IgnoreAccess) { // Check that the base class can be accessed. switch (CheckBaseClassAccess(Loc, Base, Derived, Paths.front(), InaccessibleBaseID)) { case AR_inaccessible: return true; case AR_accessible: case AR_dependent: case AR_delayed: break; } } // Build a base path if necessary. if (BasePath) BuildBasePathArray(Paths, *BasePath); return false; } if (AmbigiousBaseConvID) { // We know that the derived-to-base conversion is ambiguous, and // we're going to produce a diagnostic. Perform the derived-to-base // search just one more time to compute all of the possible paths so // that we can print them out. This is more expensive than any of // the previous derived-to-base checks we've done, but at this point // performance isn't as much of an issue. Paths.clear(); Paths.setRecordingPaths(true); bool StillOkay = IsDerivedFrom(Loc, Derived, Base, Paths); assert(StillOkay && "Can only be used with a derived-to-base conversion"); (void)StillOkay; // Build up a textual representation of the ambiguous paths, e.g., // D -> B -> A, that will be used to illustrate the ambiguous // conversions in the diagnostic. We only print one of the paths // to each base class subobject. std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths); Diag(Loc, AmbigiousBaseConvID) << Derived << Base << PathDisplayStr << Range << Name; } return true; } bool Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, SourceLocation Loc, SourceRange Range, CXXCastPath *BasePath, bool IgnoreAccess) { return CheckDerivedToBaseConversion( Derived, Base, diag::err_upcast_to_inaccessible_base, diag::err_ambiguous_derived_to_base_conv, Loc, Range, DeclarationName(), BasePath, IgnoreAccess); } /// @brief Builds a string representing ambiguous paths from a /// specific derived class to different subobjects of the same base /// class. /// /// This function builds a string that can be used in error messages /// to show the different paths that one can take through the /// inheritance hierarchy to go from the derived class to different /// subobjects of a base class. The result looks something like this: /// @code /// struct D -> struct B -> struct A /// struct D -> struct C -> struct A /// @endcode std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) { std::string PathDisplayStr; std::set DisplayedPaths; for (CXXBasePaths::paths_iterator Path = Paths.begin(); Path != Paths.end(); ++Path) { if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) { // We haven't displayed a path to this particular base // class subobject yet. PathDisplayStr += "\n "; PathDisplayStr += Context.getTypeDeclType(Paths.getOrigin()).getAsString(); for (CXXBasePath::const_iterator Element = Path->begin(); Element != Path->end(); ++Element) PathDisplayStr += " -> " + Element->Base->getType().getAsString(); } } return PathDisplayStr; } //===----------------------------------------------------------------------===// // C++ class member Handling //===----------------------------------------------------------------------===// /// ActOnAccessSpecifier - Parsed an access specifier followed by a colon. bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, SourceLocation ColonLoc, AttributeList *Attrs) { assert(Access != AS_none && "Invalid kind for syntactic access specifier!"); AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext, ASLoc, ColonLoc); CurContext->addHiddenDecl(ASDecl); return ProcessAccessDeclAttributeList(ASDecl, Attrs); } /// CheckOverrideControl - Check C++11 override control semantics. void Sema::CheckOverrideControl(NamedDecl *D) { if (D->isInvalidDecl()) return; // We only care about "override" and "final" declarations. if (!D->hasAttr() && !D->hasAttr()) return; CXXMethodDecl *MD = dyn_cast(D); // We can't check dependent instance methods. if (MD && MD->isInstance() && (MD->getParent()->hasAnyDependentBases() || MD->getType()->isDependentType())) return; if (MD && !MD->isVirtual()) { // If we have a non-virtual method, check if if hides a virtual method. // (In that case, it's most likely the method has the wrong type.) SmallVector OverloadedMethods; FindHiddenVirtualMethods(MD, OverloadedMethods); if (!OverloadedMethods.empty()) { if (OverrideAttr *OA = D->getAttr()) { Diag(OA->getLocation(), diag::override_keyword_hides_virtual_member_function) << "override" << (OverloadedMethods.size() > 1); } else if (FinalAttr *FA = D->getAttr()) { Diag(FA->getLocation(), diag::override_keyword_hides_virtual_member_function) << (FA->isSpelledAsSealed() ? "sealed" : "final") << (OverloadedMethods.size() > 1); } NoteHiddenVirtualMethods(MD, OverloadedMethods); MD->setInvalidDecl(); return; } // Fall through into the general case diagnostic. // FIXME: We might want to attempt typo correction here. } if (!MD || !MD->isVirtual()) { if (OverrideAttr *OA = D->getAttr()) { Diag(OA->getLocation(), diag::override_keyword_only_allowed_on_virtual_member_functions) << "override" << FixItHint::CreateRemoval(OA->getLocation()); D->dropAttr(); } if (FinalAttr *FA = D->getAttr()) { Diag(FA->getLocation(), diag::override_keyword_only_allowed_on_virtual_member_functions) << (FA->isSpelledAsSealed() ? "sealed" : "final") << FixItHint::CreateRemoval(FA->getLocation()); D->dropAttr(); } return; } // C++11 [class.virtual]p5: // If a function is marked with the virt-specifier override and // does not override a member function of a base class, the program is // ill-formed. bool HasOverriddenMethods = MD->begin_overridden_methods() != MD->end_overridden_methods(); if (MD->hasAttr() && !HasOverriddenMethods) Diag(MD->getLocation(), diag::err_function_marked_override_not_overriding) << MD->getDeclName(); } void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) { if (D->isInvalidDecl() || D->hasAttr()) return; CXXMethodDecl *MD = dyn_cast(D); if (!MD || MD->isImplicit() || MD->hasAttr()) return; SourceLocation Loc = MD->getLocation(); SourceLocation SpellingLoc = Loc; if (getSourceManager().isMacroArgExpansion(Loc)) SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).first; SpellingLoc = getSourceManager().getSpellingLoc(SpellingLoc); if (SpellingLoc.isValid() && getSourceManager().isInSystemHeader(SpellingLoc)) return; if (MD->size_overridden_methods() > 0) { unsigned DiagID = isa(MD) ? diag::warn_destructor_marked_not_override_overriding : diag::warn_function_marked_not_override_overriding; Diag(MD->getLocation(), DiagID) << MD->getDeclName(); const CXXMethodDecl *OMD = *MD->begin_overridden_methods(); Diag(OMD->getLocation(), diag::note_overridden_virtual_function); } } /// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member /// function overrides a virtual member function marked 'final', according to /// C++11 [class.virtual]p4. bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, const CXXMethodDecl *Old) { FinalAttr *FA = Old->getAttr(); if (!FA) return false; Diag(New->getLocation(), diag::err_final_function_overridden) << New->getDeclName() << FA->isSpelledAsSealed(); Diag(Old->getLocation(), diag::note_overridden_virtual_function); return true; } static bool InitializationHasSideEffects(const FieldDecl &FD) { const Type *T = FD.getType()->getBaseElementTypeUnsafe(); // FIXME: Destruction of ObjC lifetime types has side-effects. if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) return !RD->isCompleteDefinition() || !RD->hasTrivialDefaultConstructor() || !RD->hasTrivialDestructor(); return false; } static AttributeList *getMSPropertyAttr(AttributeList *list) { for (AttributeList *it = list; it != nullptr; it = it->getNext()) if (it->isDeclspecPropertyAttribute()) return it; return nullptr; } // Check if there is a field shadowing. void Sema::CheckShadowInheritedFields(const SourceLocation &Loc, DeclarationName FieldName, const CXXRecordDecl *RD) { if (Diags.isIgnored(diag::warn_shadow_field, Loc)) return; // To record a shadowed field in a base std::map Bases; auto FieldShadowed = [&](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { const auto Base = Specifier->getType()->getAsCXXRecordDecl(); // Record an ambiguous path directly if (Bases.find(Base) != Bases.end()) return true; for (const auto Field : Base->lookup(FieldName)) { if ((isa(Field) || isa(Field)) && Field->getAccess() != AS_private) { assert(Field->getAccess() != AS_none); assert(Bases.find(Base) == Bases.end()); Bases[Base] = Field; return true; } } return false; }; CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/true); if (!RD->lookupInBases(FieldShadowed, Paths)) return; for (const auto &P : Paths) { auto Base = P.back().Base->getType()->getAsCXXRecordDecl(); auto It = Bases.find(Base); // Skip duplicated bases if (It == Bases.end()) continue; auto BaseField = It->second; assert(BaseField->getAccess() != AS_private); if (AS_none != CXXRecordDecl::MergeAccess(P.Access, BaseField->getAccess())) { Diag(Loc, diag::warn_shadow_field) << FieldName.getAsString() << RD->getName() << Base->getName(); Diag(BaseField->getLocation(), diag::note_shadow_field); Bases.erase(It); } } } /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member /// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the /// bitfield width if there is one, 'InitExpr' specifies the initializer if /// one has been parsed, and 'InitStyle' is set if an in-class initializer is /// present (but parsing it has been deferred). NamedDecl * Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, Expr *BW, const VirtSpecifiers &VS, InClassInitStyle InitStyle) { const DeclSpec &DS = D.getDeclSpec(); DeclarationNameInfo NameInfo = GetNameForDeclarator(D); DeclarationName Name = NameInfo.getName(); SourceLocation Loc = NameInfo.getLoc(); // For anonymous bitfields, the location should point to the type. if (Loc.isInvalid()) Loc = D.getLocStart(); Expr *BitWidth = static_cast(BW); assert(isa(CurContext)); assert(!DS.isFriendSpecified()); bool isFunc = D.isDeclarationOfFunction(); if (cast(CurContext)->isInterface()) { // The Microsoft extension __interface only permits public member functions // and prohibits constructors, destructors, operators, non-public member // functions, static methods and data members. unsigned InvalidDecl; bool ShowDeclName = true; if (!isFunc) InvalidDecl = (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) ? 0 : 1; else if (AS != AS_public) InvalidDecl = 2; else if (DS.getStorageClassSpec() == DeclSpec::SCS_static) InvalidDecl = 3; else switch (Name.getNameKind()) { case DeclarationName::CXXConstructorName: InvalidDecl = 4; ShowDeclName = false; break; case DeclarationName::CXXDestructorName: InvalidDecl = 5; ShowDeclName = false; break; case DeclarationName::CXXOperatorName: case DeclarationName::CXXConversionFunctionName: InvalidDecl = 6; break; default: InvalidDecl = 0; break; } if (InvalidDecl) { if (ShowDeclName) Diag(Loc, diag::err_invalid_member_in_interface) << (InvalidDecl-1) << Name; else Diag(Loc, diag::err_invalid_member_in_interface) << (InvalidDecl-1) << ""; return nullptr; } } // C++ 9.2p6: A member shall not be declared to have automatic storage // duration (auto, register) or with the extern storage-class-specifier. // C++ 7.1.1p8: The mutable specifier can be applied only to names of class // data members and cannot be applied to names declared const or static, // and cannot be applied to reference members. switch (DS.getStorageClassSpec()) { case DeclSpec::SCS_unspecified: case DeclSpec::SCS_typedef: case DeclSpec::SCS_static: break; case DeclSpec::SCS_mutable: if (isFunc) { Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_function); // FIXME: It would be nicer if the keyword was ignored only for this // declarator. Otherwise we could get follow-up errors. D.getMutableDeclSpec().ClearStorageClassSpecs(); } break; default: Diag(DS.getStorageClassSpecLoc(), diag::err_storageclass_invalid_for_member); D.getMutableDeclSpec().ClearStorageClassSpecs(); break; } bool isInstField = ((DS.getStorageClassSpec() == DeclSpec::SCS_unspecified || DS.getStorageClassSpec() == DeclSpec::SCS_mutable) && !isFunc); if (DS.isConstexprSpecified() && isInstField) { SemaDiagnosticBuilder B = Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr_member); SourceLocation ConstexprLoc = DS.getConstexprSpecLoc(); if (InitStyle == ICIS_NoInit) { B << 0 << 0; if (D.getDeclSpec().getTypeQualifiers() & DeclSpec::TQ_const) B << FixItHint::CreateRemoval(ConstexprLoc); else { B << FixItHint::CreateReplacement(ConstexprLoc, "const"); D.getMutableDeclSpec().ClearConstexprSpec(); const char *PrevSpec; unsigned DiagID; bool Failed = D.getMutableDeclSpec().SetTypeQual( DeclSpec::TQ_const, ConstexprLoc, PrevSpec, DiagID, getLangOpts()); (void)Failed; assert(!Failed && "Making a constexpr member const shouldn't fail"); } } else { B << 1; const char *PrevSpec; unsigned DiagID; if (D.getMutableDeclSpec().SetStorageClassSpec( *this, DeclSpec::SCS_static, ConstexprLoc, PrevSpec, DiagID, Context.getPrintingPolicy())) { assert(DS.getStorageClassSpec() == DeclSpec::SCS_mutable && "This is the only DeclSpec that should fail to be applied"); B << 1; } else { B << 0 << FixItHint::CreateInsertion(ConstexprLoc, "static "); isInstField = false; } } } NamedDecl *Member; if (isInstField) { CXXScopeSpec &SS = D.getCXXScopeSpec(); // Data members must have identifiers for names. if (!Name.isIdentifier()) { Diag(Loc, diag::err_bad_variable_name) << Name; return nullptr; } IdentifierInfo *II = Name.getAsIdentifierInfo(); // Member field could not be with "template" keyword. // So TemplateParameterLists should be empty in this case. if (TemplateParameterLists.size()) { TemplateParameterList* TemplateParams = TemplateParameterLists[0]; if (TemplateParams->size()) { // There is no such thing as a member field template. Diag(D.getIdentifierLoc(), diag::err_template_member) << II << SourceRange(TemplateParams->getTemplateLoc(), TemplateParams->getRAngleLoc()); } else { // There is an extraneous 'template<>' for this member. Diag(TemplateParams->getTemplateLoc(), diag::err_template_member_noparams) << II << SourceRange(TemplateParams->getTemplateLoc(), TemplateParams->getRAngleLoc()); } return nullptr; } if (SS.isSet() && !SS.isInvalid()) { // The user provided a superfluous scope specifier inside a class // definition: // // class X { // int X::member; // }; if (DeclContext *DC = computeDeclContext(SS, false)) diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc()); else Diag(D.getIdentifierLoc(), diag::err_member_qualification) << Name << SS.getRange(); SS.clear(); } AttributeList *MSPropertyAttr = getMSPropertyAttr(D.getDeclSpec().getAttributes().getList()); if (MSPropertyAttr) { Member = HandleMSProperty(S, cast(CurContext), Loc, D, BitWidth, InitStyle, AS, MSPropertyAttr); if (!Member) return nullptr; isInstField = false; } else { Member = HandleField(S, cast(CurContext), Loc, D, BitWidth, InitStyle, AS); if (!Member) return nullptr; } CheckShadowInheritedFields(Loc, Name, cast(CurContext)); } else { Member = HandleDeclarator(S, D, TemplateParameterLists); if (!Member) return nullptr; // Non-instance-fields can't have a bitfield. if (BitWidth) { if (Member->isInvalidDecl()) { // don't emit another diagnostic. } else if (isa(Member) || isa(Member)) { // C++ 9.6p3: A bit-field shall not be a static member. // "static member 'A' cannot be a bit-field" Diag(Loc, diag::err_static_not_bitfield) << Name << BitWidth->getSourceRange(); } else if (isa(Member)) { // "typedef member 'x' cannot be a bit-field" Diag(Loc, diag::err_typedef_not_bitfield) << Name << BitWidth->getSourceRange(); } else { // A function typedef ("typedef int f(); f a;"). // C++ 9.6p3: A bit-field shall have integral or enumeration type. Diag(Loc, diag::err_not_integral_type_bitfield) << Name << cast(Member)->getType() << BitWidth->getSourceRange(); } BitWidth = nullptr; Member->setInvalidDecl(); } Member->setAccess(AS); // If we have declared a member function template or static data member // template, set the access of the templated declaration as well. if (FunctionTemplateDecl *FunTmpl = dyn_cast(Member)) FunTmpl->getTemplatedDecl()->setAccess(AS); else if (VarTemplateDecl *VarTmpl = dyn_cast(Member)) VarTmpl->getTemplatedDecl()->setAccess(AS); } if (VS.isOverrideSpecified()) Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context, 0)); if (VS.isFinalSpecified()) Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context, VS.isFinalSpelledSealed())); if (VS.getLastLocation().isValid()) { // Update the end location of a method that has a virt-specifiers. if (CXXMethodDecl *MD = dyn_cast_or_null(Member)) MD->setRangeEnd(VS.getLastLocation()); } CheckOverrideControl(Member); assert((Name || isInstField) && "No identifier for non-field ?"); if (isInstField) { FieldDecl *FD = cast(Member); FieldCollector->Add(FD); if (!Diags.isIgnored(diag::warn_unused_private_field, FD->getLocation())) { // Remember all explicit private FieldDecls that have a name, no side // effects and are not part of a dependent type declaration. if (!FD->isImplicit() && FD->getDeclName() && FD->getAccess() == AS_private && !FD->hasAttr() && !FD->getParent()->isDependentContext() && !InitializationHasSideEffects(*FD)) UnusedPrivateFields.insert(FD); } } return Member; } namespace { class UninitializedFieldVisitor : public EvaluatedExprVisitor { Sema &S; // List of Decls to generate a warning on. Also remove Decls that become // initialized. llvm::SmallPtrSetImpl &Decls; // List of base classes of the record. Classes are removed after their // initializers. llvm::SmallPtrSetImpl &BaseClasses; // Vector of decls to be removed from the Decl set prior to visiting the // nodes. These Decls may have been initialized in the prior initializer. llvm::SmallVector DeclsToRemove; // If non-null, add a note to the warning pointing back to the constructor. const CXXConstructorDecl *Constructor; // Variables to hold state when processing an initializer list. When // InitList is true, special case initialization of FieldDecls matching // InitListFieldDecl. bool InitList; FieldDecl *InitListFieldDecl; llvm::SmallVector InitFieldIndex; public: typedef EvaluatedExprVisitor Inherited; UninitializedFieldVisitor(Sema &S, llvm::SmallPtrSetImpl &Decls, llvm::SmallPtrSetImpl &BaseClasses) : Inherited(S.Context), S(S), Decls(Decls), BaseClasses(BaseClasses), Constructor(nullptr), InitList(false), InitListFieldDecl(nullptr) {} // Returns true if the use of ME is not an uninitialized use. bool IsInitListMemberExprInitialized(MemberExpr *ME, bool CheckReferenceOnly) { llvm::SmallVector Fields; bool ReferenceField = false; while (ME) { FieldDecl *FD = dyn_cast(ME->getMemberDecl()); if (!FD) return false; Fields.push_back(FD); if (FD->getType()->isReferenceType()) ReferenceField = true; ME = dyn_cast(ME->getBase()->IgnoreParenImpCasts()); } // Binding a reference to an unintialized field is not an // uninitialized use. if (CheckReferenceOnly && !ReferenceField) return true; llvm::SmallVector UsedFieldIndex; // Discard the first field since it is the field decl that is being // initialized. for (auto I = Fields.rbegin() + 1, E = Fields.rend(); I != E; ++I) { UsedFieldIndex.push_back((*I)->getFieldIndex()); } for (auto UsedIter = UsedFieldIndex.begin(), UsedEnd = UsedFieldIndex.end(), OrigIter = InitFieldIndex.begin(), OrigEnd = InitFieldIndex.end(); UsedIter != UsedEnd && OrigIter != OrigEnd; ++UsedIter, ++OrigIter) { if (*UsedIter < *OrigIter) return true; if (*UsedIter > *OrigIter) break; } return false; } void HandleMemberExpr(MemberExpr *ME, bool CheckReferenceOnly, bool AddressOf) { if (isa(ME->getMemberDecl())) return; // FieldME is the inner-most MemberExpr that is not an anonymous struct // or union. MemberExpr *FieldME = ME; bool AllPODFields = FieldME->getType().isPODType(S.Context); Expr *Base = ME; while (MemberExpr *SubME = dyn_cast(Base->IgnoreParenImpCasts())) { if (isa(SubME->getMemberDecl())) return; if (FieldDecl *FD = dyn_cast(SubME->getMemberDecl())) if (!FD->isAnonymousStructOrUnion()) FieldME = SubME; if (!FieldME->getType().isPODType(S.Context)) AllPODFields = false; Base = SubME->getBase(); } if (!isa(Base->IgnoreParenImpCasts())) return; if (AddressOf && AllPODFields) return; ValueDecl* FoundVD = FieldME->getMemberDecl(); if (ImplicitCastExpr *BaseCast = dyn_cast(Base)) { while (isa(BaseCast->getSubExpr())) { BaseCast = cast(BaseCast->getSubExpr()); } if (BaseCast->getCastKind() == CK_UncheckedDerivedToBase) { QualType T = BaseCast->getType(); if (T->isPointerType() && BaseClasses.count(T->getPointeeType())) { S.Diag(FieldME->getExprLoc(), diag::warn_base_class_is_uninit) << T->getPointeeType() << FoundVD; } } } if (!Decls.count(FoundVD)) return; const bool IsReference = FoundVD->getType()->isReferenceType(); if (InitList && !AddressOf && FoundVD == InitListFieldDecl) { // Special checking for initializer lists. if (IsInitListMemberExprInitialized(ME, CheckReferenceOnly)) { return; } } else { // Prevent double warnings on use of unbounded references. if (CheckReferenceOnly && !IsReference) return; } unsigned diag = IsReference ? diag::warn_reference_field_is_uninit : diag::warn_field_is_uninit; S.Diag(FieldME->getExprLoc(), diag) << FoundVD; if (Constructor) S.Diag(Constructor->getLocation(), diag::note_uninit_in_this_constructor) << (Constructor->isDefaultConstructor() && Constructor->isImplicit()); } void HandleValue(Expr *E, bool AddressOf) { E = E->IgnoreParens(); if (MemberExpr *ME = dyn_cast(E)) { HandleMemberExpr(ME, false /*CheckReferenceOnly*/, AddressOf /*AddressOf*/); return; } if (ConditionalOperator *CO = dyn_cast(E)) { Visit(CO->getCond()); HandleValue(CO->getTrueExpr(), AddressOf); HandleValue(CO->getFalseExpr(), AddressOf); return; } if (BinaryConditionalOperator *BCO = dyn_cast(E)) { Visit(BCO->getCond()); HandleValue(BCO->getFalseExpr(), AddressOf); return; } if (OpaqueValueExpr *OVE = dyn_cast(E)) { HandleValue(OVE->getSourceExpr(), AddressOf); return; } if (BinaryOperator *BO = dyn_cast(E)) { switch (BO->getOpcode()) { default: break; case(BO_PtrMemD): case(BO_PtrMemI): HandleValue(BO->getLHS(), AddressOf); Visit(BO->getRHS()); return; case(BO_Comma): Visit(BO->getLHS()); HandleValue(BO->getRHS(), AddressOf); return; } } Visit(E); } void CheckInitListExpr(InitListExpr *ILE) { InitFieldIndex.push_back(0); for (auto Child : ILE->children()) { if (InitListExpr *SubList = dyn_cast(Child)) { CheckInitListExpr(SubList); } else { Visit(Child); } ++InitFieldIndex.back(); } InitFieldIndex.pop_back(); } void CheckInitializer(Expr *E, const CXXConstructorDecl *FieldConstructor, FieldDecl *Field, const Type *BaseClass) { // Remove Decls that may have been initialized in the previous // initializer. for (ValueDecl* VD : DeclsToRemove) Decls.erase(VD); DeclsToRemove.clear(); Constructor = FieldConstructor; InitListExpr *ILE = dyn_cast(E); if (ILE && Field) { InitList = true; InitListFieldDecl = Field; InitFieldIndex.clear(); CheckInitListExpr(ILE); } else { InitList = false; Visit(E); } if (Field) Decls.erase(Field); if (BaseClass) BaseClasses.erase(BaseClass->getCanonicalTypeInternal()); } void VisitMemberExpr(MemberExpr *ME) { // All uses of unbounded reference fields will warn. HandleMemberExpr(ME, true /*CheckReferenceOnly*/, false /*AddressOf*/); } void VisitImplicitCastExpr(ImplicitCastExpr *E) { if (E->getCastKind() == CK_LValueToRValue) { HandleValue(E->getSubExpr(), false /*AddressOf*/); return; } Inherited::VisitImplicitCastExpr(E); } void VisitCXXConstructExpr(CXXConstructExpr *E) { if (E->getConstructor()->isCopyConstructor()) { Expr *ArgExpr = E->getArg(0); if (InitListExpr *ILE = dyn_cast(ArgExpr)) if (ILE->getNumInits() == 1) ArgExpr = ILE->getInit(0); if (ImplicitCastExpr *ICE = dyn_cast(ArgExpr)) if (ICE->getCastKind() == CK_NoOp) ArgExpr = ICE->getSubExpr(); HandleValue(ArgExpr, false /*AddressOf*/); return; } Inherited::VisitCXXConstructExpr(E); } void VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { Expr *Callee = E->getCallee(); if (isa(Callee)) { HandleValue(Callee, false /*AddressOf*/); for (auto Arg : E->arguments()) Visit(Arg); return; } Inherited::VisitCXXMemberCallExpr(E); } void VisitCallExpr(CallExpr *E) { // Treat std::move as a use. if (E->getNumArgs() == 1) { if (FunctionDecl *FD = E->getDirectCallee()) { if (FD->isInStdNamespace() && FD->getIdentifier() && FD->getIdentifier()->isStr("move")) { HandleValue(E->getArg(0), false /*AddressOf*/); return; } } } Inherited::VisitCallExpr(E); } void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { Expr *Callee = E->getCallee(); if (isa(Callee)) return Inherited::VisitCXXOperatorCallExpr(E); Visit(Callee); for (auto Arg : E->arguments()) HandleValue(Arg->IgnoreParenImpCasts(), false /*AddressOf*/); } void VisitBinaryOperator(BinaryOperator *E) { // If a field assignment is detected, remove the field from the // uninitiailized field set. if (E->getOpcode() == BO_Assign) if (MemberExpr *ME = dyn_cast(E->getLHS())) if (FieldDecl *FD = dyn_cast(ME->getMemberDecl())) if (!FD->getType()->isReferenceType()) DeclsToRemove.push_back(FD); if (E->isCompoundAssignmentOp()) { HandleValue(E->getLHS(), false /*AddressOf*/); Visit(E->getRHS()); return; } Inherited::VisitBinaryOperator(E); } void VisitUnaryOperator(UnaryOperator *E) { if (E->isIncrementDecrementOp()) { HandleValue(E->getSubExpr(), false /*AddressOf*/); return; } if (E->getOpcode() == UO_AddrOf) { if (MemberExpr *ME = dyn_cast(E->getSubExpr())) { HandleValue(ME->getBase(), true /*AddressOf*/); return; } } Inherited::VisitUnaryOperator(E); } }; // Diagnose value-uses of fields to initialize themselves, e.g. // foo(foo) // where foo is not also a parameter to the constructor. // Also diagnose across field uninitialized use such as // x(y), y(x) // TODO: implement -Wuninitialized and fold this into that framework. static void DiagnoseUninitializedFields( Sema &SemaRef, const CXXConstructorDecl *Constructor) { if (SemaRef.getDiagnostics().isIgnored(diag::warn_field_is_uninit, Constructor->getLocation())) { return; } if (Constructor->isInvalidDecl()) return; const CXXRecordDecl *RD = Constructor->getParent(); if (RD->getDescribedClassTemplate()) return; // Holds fields that are uninitialized. llvm::SmallPtrSet UninitializedFields; // At the beginning, all fields are uninitialized. for (auto *I : RD->decls()) { if (auto *FD = dyn_cast(I)) { UninitializedFields.insert(FD); } else if (auto *IFD = dyn_cast(I)) { UninitializedFields.insert(IFD->getAnonField()); } } llvm::SmallPtrSet UninitializedBaseClasses; for (auto I : RD->bases()) UninitializedBaseClasses.insert(I.getType().getCanonicalType()); if (UninitializedFields.empty() && UninitializedBaseClasses.empty()) return; UninitializedFieldVisitor UninitializedChecker(SemaRef, UninitializedFields, UninitializedBaseClasses); for (const auto *FieldInit : Constructor->inits()) { if (UninitializedFields.empty() && UninitializedBaseClasses.empty()) break; Expr *InitExpr = FieldInit->getInit(); if (!InitExpr) continue; if (CXXDefaultInitExpr *Default = dyn_cast(InitExpr)) { InitExpr = Default->getExpr(); if (!InitExpr) continue; // In class initializers will point to the constructor. UninitializedChecker.CheckInitializer(InitExpr, Constructor, FieldInit->getAnyMember(), FieldInit->getBaseClass()); } else { UninitializedChecker.CheckInitializer(InitExpr, nullptr, FieldInit->getAnyMember(), FieldInit->getBaseClass()); } } } } // namespace /// \brief Enter a new C++ default initializer scope. After calling this, the /// caller must call \ref ActOnFinishCXXInClassMemberInitializer, even if /// parsing or instantiating the initializer failed. void Sema::ActOnStartCXXInClassMemberInitializer() { // Create a synthetic function scope to represent the call to the constructor // that notionally surrounds a use of this initializer. PushFunctionScope(); } /// \brief This is invoked after parsing an in-class initializer for a /// non-static C++ class member, and after instantiating an in-class initializer /// in a class template. Such actions are deferred until the class is complete. void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc, Expr *InitExpr) { // Pop the notional constructor scope we created earlier. PopFunctionScopeInfo(nullptr, D); FieldDecl *FD = dyn_cast(D); assert((isa(D) || FD->getInClassInitStyle() != ICIS_NoInit) && "must set init style when field is created"); if (!InitExpr) { D->setInvalidDecl(); if (FD) FD->removeInClassInitializer(); return; } if (DiagnoseUnexpandedParameterPack(InitExpr, UPPC_Initializer)) { FD->setInvalidDecl(); FD->removeInClassInitializer(); return; } ExprResult Init = InitExpr; if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { InitializedEntity Entity = InitializedEntity::InitializeMember(FD); InitializationKind Kind = FD->getInClassInitStyle() == ICIS_ListInit ? InitializationKind::CreateDirectList(InitExpr->getLocStart()) : InitializationKind::CreateCopy(InitExpr->getLocStart(), InitLoc); InitializationSequence Seq(*this, Entity, Kind, InitExpr); Init = Seq.Perform(*this, Entity, Kind, InitExpr); if (Init.isInvalid()) { FD->setInvalidDecl(); return; } } // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. Init = ActOnFinishFullExpr(Init.get(), InitLoc); if (Init.isInvalid()) { FD->setInvalidDecl(); return; } InitExpr = Init.get(); FD->setInClassInitializer(InitExpr); } /// \brief Find the direct and/or virtual base specifiers that /// correspond to the given base type, for use in base initialization /// within a constructor. static bool FindBaseInitializer(Sema &SemaRef, CXXRecordDecl *ClassDecl, QualType BaseType, const CXXBaseSpecifier *&DirectBaseSpec, const CXXBaseSpecifier *&VirtualBaseSpec) { // First, check for a direct base class. DirectBaseSpec = nullptr; for (const auto &Base : ClassDecl->bases()) { if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base.getType())) { // We found a direct base of this type. That's what we're // initializing. DirectBaseSpec = &Base; break; } } // Check for a virtual base class. // FIXME: We might be able to short-circuit this if we know in advance that // there are no virtual bases. VirtualBaseSpec = nullptr; if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) { // We haven't found a base yet; search the class hierarchy for a // virtual base class. CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/false); if (SemaRef.IsDerivedFrom(ClassDecl->getLocation(), SemaRef.Context.getTypeDeclType(ClassDecl), BaseType, Paths)) { for (CXXBasePaths::paths_iterator Path = Paths.begin(); Path != Paths.end(); ++Path) { if (Path->back().Base->isVirtual()) { VirtualBaseSpec = Path->back().Base; break; } } } } return DirectBaseSpec || VirtualBaseSpec; } /// \brief Handle a C++ member initializer using braced-init-list syntax. MemInitResult Sema::ActOnMemInitializer(Decl *ConstructorD, Scope *S, CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy, const DeclSpec &DS, SourceLocation IdLoc, Expr *InitList, SourceLocation EllipsisLoc) { return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, DS, IdLoc, InitList, EllipsisLoc); } /// \brief Handle a C++ member initializer using parentheses syntax. MemInitResult Sema::ActOnMemInitializer(Decl *ConstructorD, Scope *S, CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy, const DeclSpec &DS, SourceLocation IdLoc, SourceLocation LParenLoc, ArrayRef Args, SourceLocation RParenLoc, SourceLocation EllipsisLoc) { Expr *List = new (Context) ParenListExpr(Context, LParenLoc, Args, RParenLoc); return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, DS, IdLoc, List, EllipsisLoc); } namespace { // Callback to only accept typo corrections that can be a valid C++ member // intializer: either a non-static field member or a base class. class MemInitializerValidatorCCC : public CorrectionCandidateCallback { public: explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl) : ClassDecl(ClassDecl) {} bool ValidateCandidate(const TypoCorrection &candidate) override { if (NamedDecl *ND = candidate.getCorrectionDecl()) { if (FieldDecl *Member = dyn_cast(ND)) return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl); return isa(ND); } return false; } private: CXXRecordDecl *ClassDecl; }; } /// \brief Handle a C++ member initializer. MemInitResult Sema::BuildMemInitializer(Decl *ConstructorD, Scope *S, CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy, const DeclSpec &DS, SourceLocation IdLoc, Expr *Init, SourceLocation EllipsisLoc) { ExprResult Res = CorrectDelayedTyposInExpr(Init); if (!Res.isUsable()) return true; Init = Res.get(); if (!ConstructorD) return true; AdjustDeclIfTemplate(ConstructorD); CXXConstructorDecl *Constructor = dyn_cast(ConstructorD); if (!Constructor) { // The user wrote a constructor initializer on a function that is // not a C++ constructor. Ignore the error for now, because we may // have more member initializers coming; we'll diagnose it just // once in ActOnMemInitializers. return true; } CXXRecordDecl *ClassDecl = Constructor->getParent(); // C++ [class.base.init]p2: // Names in a mem-initializer-id are looked up in the scope of the // constructor's class and, if not found in that scope, are looked // up in the scope containing the constructor's definition. // [Note: if the constructor's class contains a member with the // same name as a direct or virtual base class of the class, a // mem-initializer-id naming the member or base class and composed // of a single identifier refers to the class member. A // mem-initializer-id for the hidden base class may be specified // using a qualified name. ] if (!SS.getScopeRep() && !TemplateTypeTy) { // Look for a member, first. DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase); if (!Result.empty()) { ValueDecl *Member; if ((Member = dyn_cast(Result.front())) || (Member = dyn_cast(Result.front()))) { if (EllipsisLoc.isValid()) Diag(EllipsisLoc, diag::err_pack_expansion_member_init) << MemberOrBase << SourceRange(IdLoc, Init->getSourceRange().getEnd()); return BuildMemberInitializer(Member, Init, IdLoc); } } } // It didn't name a member, so see if it names a class. QualType BaseType; TypeSourceInfo *TInfo = nullptr; if (TemplateTypeTy) { BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo); } else if (DS.getTypeSpecType() == TST_decltype) { BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); } else if (DS.getTypeSpecType() == TST_decltype_auto) { Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid); return true; } else { LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName); LookupParsedName(R, S, &SS); TypeDecl *TyD = R.getAsSingle(); if (!TyD) { if (R.isAmbiguous()) return true; // We don't want access-control diagnostics here. R.suppressDiagnostics(); if (SS.isSet() && isDependentScopeSpecifier(SS)) { bool NotUnknownSpecialization = false; DeclContext *DC = computeDeclContext(SS, false); if (CXXRecordDecl *Record = dyn_cast_or_null(DC)) NotUnknownSpecialization = !Record->hasAnyDependentBases(); if (!NotUnknownSpecialization) { // When the scope specifier can refer to a member of an unknown // specialization, we take it as a type name. BaseType = CheckTypenameType(ETK_None, SourceLocation(), SS.getWithLocInContext(Context), *MemberOrBase, IdLoc); if (BaseType.isNull()) return true; TInfo = Context.CreateTypeSourceInfo(BaseType); DependentNameTypeLoc TL = TInfo->getTypeLoc().castAs(); if (!TL.isNull()) { TL.setNameLoc(IdLoc); TL.setElaboratedKeywordLoc(SourceLocation()); TL.setQualifierLoc(SS.getWithLocInContext(Context)); } R.clear(); R.setLookupName(MemberOrBase); } } // If no results were found, try to correct typos. TypoCorrection Corr; if (R.empty() && BaseType.isNull() && (Corr = CorrectTypo( R.getLookupNameInfo(), R.getLookupKind(), S, &SS, llvm::make_unique(ClassDecl), CTK_ErrorRecovery, ClassDecl))) { if (FieldDecl *Member = Corr.getCorrectionDeclAs()) { // We have found a non-static data member with a similar // name to what was typed; complain and initialize that // member. diagnoseTypo(Corr, PDiag(diag::err_mem_init_not_member_or_class_suggest) << MemberOrBase << true); return BuildMemberInitializer(Member, Init, IdLoc); } else if (TypeDecl *Type = Corr.getCorrectionDeclAs()) { const CXXBaseSpecifier *DirectBaseSpec; const CXXBaseSpecifier *VirtualBaseSpec; if (FindBaseInitializer(*this, ClassDecl, Context.getTypeDeclType(Type), DirectBaseSpec, VirtualBaseSpec)) { // We have found a direct or virtual base class with a // similar name to what was typed; complain and initialize // that base class. diagnoseTypo(Corr, PDiag(diag::err_mem_init_not_member_or_class_suggest) << MemberOrBase << false, PDiag() /*Suppress note, we provide our own.*/); const CXXBaseSpecifier *BaseSpec = DirectBaseSpec ? DirectBaseSpec : VirtualBaseSpec; Diag(BaseSpec->getLocStart(), diag::note_base_class_specified_here) << BaseSpec->getType() << BaseSpec->getSourceRange(); TyD = Type; } } } if (!TyD && BaseType.isNull()) { Diag(IdLoc, diag::err_mem_init_not_member_or_class) << MemberOrBase << SourceRange(IdLoc,Init->getSourceRange().getEnd()); return true; } } if (BaseType.isNull()) { BaseType = Context.getTypeDeclType(TyD); MarkAnyDeclReferenced(TyD->getLocation(), TyD, /*OdrUse=*/false); if (SS.isSet()) { BaseType = Context.getElaboratedType(ETK_None, SS.getScopeRep(), BaseType); TInfo = Context.CreateTypeSourceInfo(BaseType); ElaboratedTypeLoc TL = TInfo->getTypeLoc().castAs(); TL.getNamedTypeLoc().castAs().setNameLoc(IdLoc); TL.setElaboratedKeywordLoc(SourceLocation()); TL.setQualifierLoc(SS.getWithLocInContext(Context)); } } } if (!TInfo) TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc); return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc); } /// Checks a member initializer expression for cases where reference (or /// pointer) members are bound to by-value parameters (or their addresses). static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member, Expr *Init, SourceLocation IdLoc) { QualType MemberTy = Member->getType(); // We only handle pointers and references currently. // FIXME: Would this be relevant for ObjC object pointers? Or block pointers? if (!MemberTy->isReferenceType() && !MemberTy->isPointerType()) return; const bool IsPointer = MemberTy->isPointerType(); if (IsPointer) { if (const UnaryOperator *Op = dyn_cast(Init->IgnoreParenImpCasts())) { // The only case we're worried about with pointers requires taking the // address. if (Op->getOpcode() != UO_AddrOf) return; Init = Op->getSubExpr(); } else { // We only handle address-of expression initializers for pointers. return; } } if (const DeclRefExpr *DRE = dyn_cast(Init->IgnoreParens())) { // We only warn when referring to a non-reference parameter declaration. const ParmVarDecl *Parameter = dyn_cast(DRE->getDecl()); if (!Parameter || Parameter->getType()->isReferenceType()) return; S.Diag(Init->getExprLoc(), IsPointer ? diag::warn_init_ptr_member_to_parameter_addr : diag::warn_bind_ref_member_to_parameter) << Member << Parameter << Init->getSourceRange(); } else { // Other initializers are fine. return; } S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here) << (unsigned)IsPointer; } MemInitResult Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, SourceLocation IdLoc) { FieldDecl *DirectMember = dyn_cast(Member); IndirectFieldDecl *IndirectMember = dyn_cast(Member); assert((DirectMember || IndirectMember) && "Member must be a FieldDecl or IndirectFieldDecl"); if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) return true; if (Member->isInvalidDecl()) return true; MultiExprArg Args; if (ParenListExpr *ParenList = dyn_cast(Init)) { Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs()); } else if (InitListExpr *InitList = dyn_cast(Init)) { Args = MultiExprArg(InitList->getInits(), InitList->getNumInits()); } else { // Template instantiation doesn't reconstruct ParenListExprs for us. Args = Init; } SourceRange InitRange = Init->getSourceRange(); if (Member->getType()->isDependentType() || Init->isTypeDependent()) { // Can't check initialization for a member of dependent type or when // any of the arguments are type-dependent expressions. DiscardCleanupsInEvaluationContext(); } else { bool InitList = false; if (isa(Init)) { InitList = true; Args = Init; } // Initialize the member. InitializedEntity MemberEntity = DirectMember ? InitializedEntity::InitializeMember(DirectMember, nullptr) : InitializedEntity::InitializeMember(IndirectMember, nullptr); InitializationKind Kind = InitList ? InitializationKind::CreateDirectList(IdLoc) : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(), InitRange.getEnd()); InitializationSequence InitSeq(*this, MemberEntity, Kind, Args); ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args, nullptr); if (MemberInit.isInvalid()) return true; CheckForDanglingReferenceOrPointer(*this, Member, MemberInit.get(), IdLoc); // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin()); if (MemberInit.isInvalid()) return true; Init = MemberInit.get(); } if (DirectMember) { return new (Context) CXXCtorInitializer(Context, DirectMember, IdLoc, InitRange.getBegin(), Init, InitRange.getEnd()); } else { return new (Context) CXXCtorInitializer(Context, IndirectMember, IdLoc, InitRange.getBegin(), Init, InitRange.getEnd()); } } MemInitResult Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, CXXRecordDecl *ClassDecl) { SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); if (!LangOpts.CPlusPlus11) return Diag(NameLoc, diag::err_delegating_ctor) << TInfo->getTypeLoc().getLocalSourceRange(); Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor); bool InitList = true; MultiExprArg Args = Init; if (ParenListExpr *ParenList = dyn_cast(Init)) { InitList = false; Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs()); } SourceRange InitRange = Init->getSourceRange(); // Initialize the object. InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( QualType(ClassDecl->getTypeForDecl(), 0)); InitializationKind Kind = InitList ? InitializationKind::CreateDirectList(NameLoc) : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(), InitRange.getEnd()); InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args); ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind, Args, nullptr); if (DelegationInit.isInvalid()) return true; assert(cast(DelegationInit.get())->getConstructor() && "Delegating constructor with no target?"); // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. DelegationInit = ActOnFinishFullExpr(DelegationInit.get(), InitRange.getBegin()); if (DelegationInit.isInvalid()) return true; // If we are in a dependent context, template instantiation will // perform this type-checking again. Just save the arguments that we // received in a ParenListExpr. // FIXME: This isn't quite ideal, since our ASTs don't capture all // of the information that we have about the base // initializer. However, deconstructing the ASTs is a dicey process, // and this approach is far more likely to get the corner cases right. if (CurContext->isDependentContext()) DelegationInit = Init; return new (Context) CXXCtorInitializer(Context, TInfo, InitRange.getBegin(), DelegationInit.getAs(), InitRange.getEnd()); } MemInitResult Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, Expr *Init, CXXRecordDecl *ClassDecl, SourceLocation EllipsisLoc) { SourceLocation BaseLoc = BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin(); if (!BaseType->isDependentType() && !BaseType->isRecordType()) return Diag(BaseLoc, diag::err_base_init_does_not_name_class) << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange(); // C++ [class.base.init]p2: // [...] Unless the mem-initializer-id names a nonstatic data // member of the constructor's class or a direct or virtual base // of that class, the mem-initializer is ill-formed. A // mem-initializer-list can initialize a base class using any // name that denotes that base class type. bool Dependent = BaseType->isDependentType() || Init->isTypeDependent(); SourceRange InitRange = Init->getSourceRange(); if (EllipsisLoc.isValid()) { // This is a pack expansion. if (!BaseType->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << SourceRange(BaseLoc, InitRange.getEnd()); EllipsisLoc = SourceLocation(); } } else { // Check for any unexpanded parameter packs. if (DiagnoseUnexpandedParameterPack(BaseLoc, BaseTInfo, UPPC_Initializer)) return true; if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) return true; } // Check for direct and virtual base classes. const CXXBaseSpecifier *DirectBaseSpec = nullptr; const CXXBaseSpecifier *VirtualBaseSpec = nullptr; if (!Dependent) { if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0), BaseType)) return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl); FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, VirtualBaseSpec); // C++ [base.class.init]p2: // Unless the mem-initializer-id names a nonstatic data member of the // constructor's class or a direct or virtual base of that class, the // mem-initializer is ill-formed. if (!DirectBaseSpec && !VirtualBaseSpec) { // If the class has any dependent bases, then it's possible that // one of those types will resolve to the same type as // BaseType. Therefore, just treat this as a dependent base // class initialization. FIXME: Should we try to check the // initialization anyway? It seems odd. if (ClassDecl->hasAnyDependentBases()) Dependent = true; else return Diag(BaseLoc, diag::err_not_direct_base_or_virtual) << BaseType << Context.getTypeDeclType(ClassDecl) << BaseTInfo->getTypeLoc().getLocalSourceRange(); } } if (Dependent) { DiscardCleanupsInEvaluationContext(); return new (Context) CXXCtorInitializer(Context, BaseTInfo, /*IsVirtual=*/false, InitRange.getBegin(), Init, InitRange.getEnd(), EllipsisLoc); } // C++ [base.class.init]p2: // If a mem-initializer-id is ambiguous because it designates both // a direct non-virtual base class and an inherited virtual base // class, the mem-initializer is ill-formed. if (DirectBaseSpec && VirtualBaseSpec) return Diag(BaseLoc, diag::err_base_init_direct_and_virtual) << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange(); const CXXBaseSpecifier *BaseSpec = DirectBaseSpec; if (!BaseSpec) BaseSpec = VirtualBaseSpec; // Initialize the base. bool InitList = true; MultiExprArg Args = Init; if (ParenListExpr *ParenList = dyn_cast(Init)) { InitList = false; Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs()); } InitializedEntity BaseEntity = InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec); InitializationKind Kind = InitList ? InitializationKind::CreateDirectList(BaseLoc) : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(), InitRange.getEnd()); InitializationSequence InitSeq(*this, BaseEntity, Kind, Args); ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, Args, nullptr); if (BaseInit.isInvalid()) return true; // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin()); if (BaseInit.isInvalid()) return true; // If we are in a dependent context, template instantiation will // perform this type-checking again. Just save the arguments that we // received in a ParenListExpr. // FIXME: This isn't quite ideal, since our ASTs don't capture all // of the information that we have about the base // initializer. However, deconstructing the ASTs is a dicey process, // and this approach is far more likely to get the corner cases right. if (CurContext->isDependentContext()) BaseInit = Init; return new (Context) CXXCtorInitializer(Context, BaseTInfo, BaseSpec->isVirtual(), InitRange.getBegin(), BaseInit.getAs(), InitRange.getEnd(), EllipsisLoc); } // Create a static_cast\(expr). static Expr *CastForMoving(Sema &SemaRef, Expr *E, QualType T = QualType()) { if (T.isNull()) T = E->getType(); QualType TargetType = SemaRef.BuildReferenceType( T, /*SpelledAsLValue*/false, SourceLocation(), DeclarationName()); SourceLocation ExprLoc = E->getLocStart(); TypeSourceInfo *TargetLoc = SemaRef.Context.getTrivialTypeSourceInfo( TargetType, ExprLoc); return SemaRef.BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E, SourceRange(ExprLoc, ExprLoc), E->getSourceRange()).get(); } /// ImplicitInitializerKind - How an implicit base or member initializer should /// initialize its base or member. enum ImplicitInitializerKind { IIK_Default, IIK_Copy, IIK_Move, IIK_Inherit }; static bool BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, ImplicitInitializerKind ImplicitInitKind, CXXBaseSpecifier *BaseSpec, bool IsInheritedVirtualBase, CXXCtorInitializer *&CXXBaseInit) { InitializedEntity InitEntity = InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec, IsInheritedVirtualBase); ExprResult BaseInit; switch (ImplicitInitKind) { case IIK_Inherit: case IIK_Default: { InitializationKind InitKind = InitializationKind::CreateDefault(Constructor->getLocation()); InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, None); BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, None); break; } case IIK_Move: case IIK_Copy: { bool Moving = ImplicitInitKind == IIK_Move; ParmVarDecl *Param = Constructor->getParamDecl(0); QualType ParamType = Param->getType().getNonReferenceType(); Expr *CopyCtorArg = DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), SourceLocation(), Param, false, Constructor->getLocation(), ParamType, VK_LValue, nullptr); SemaRef.MarkDeclRefReferenced(cast(CopyCtorArg)); // Cast to the base class to avoid ambiguities. QualType ArgTy = SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(), ParamType.getQualifiers()); if (Moving) { CopyCtorArg = CastForMoving(SemaRef, CopyCtorArg); } CXXCastPath BasePath; BasePath.push_back(BaseSpec); CopyCtorArg = SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy, CK_UncheckedDerivedToBase, Moving ? VK_XValue : VK_LValue, &BasePath).get(); InitializationKind InitKind = InitializationKind::CreateDirect(Constructor->getLocation(), SourceLocation(), SourceLocation()); InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, CopyCtorArg); BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, CopyCtorArg); break; } } BaseInit = SemaRef.MaybeCreateExprWithCleanups(BaseInit); if (BaseInit.isInvalid()) return true; CXXBaseInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, SemaRef.Context.getTrivialTypeSourceInfo(BaseSpec->getType(), SourceLocation()), BaseSpec->isVirtual(), SourceLocation(), BaseInit.getAs(), SourceLocation(), SourceLocation()); return false; } static bool RefersToRValueRef(Expr *MemRef) { ValueDecl *Referenced = cast(MemRef)->getMemberDecl(); return Referenced->getType()->isRValueReferenceType(); } static bool BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, ImplicitInitializerKind ImplicitInitKind, FieldDecl *Field, IndirectFieldDecl *Indirect, CXXCtorInitializer *&CXXMemberInit) { if (Field->isInvalidDecl()) return true; SourceLocation Loc = Constructor->getLocation(); if (ImplicitInitKind == IIK_Copy || ImplicitInitKind == IIK_Move) { bool Moving = ImplicitInitKind == IIK_Move; ParmVarDecl *Param = Constructor->getParamDecl(0); QualType ParamType = Param->getType().getNonReferenceType(); // Suppress copying zero-width bitfields. if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0) return false; Expr *MemberExprBase = DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), SourceLocation(), Param, false, Loc, ParamType, VK_LValue, nullptr); SemaRef.MarkDeclRefReferenced(cast(MemberExprBase)); if (Moving) { MemberExprBase = CastForMoving(SemaRef, MemberExprBase); } // Build a reference to this field within the parameter. CXXScopeSpec SS; LookupResult MemberLookup(SemaRef, Field->getDeclName(), Loc, Sema::LookupMemberName); MemberLookup.addDecl(Indirect ? cast(Indirect) : cast(Field), AS_public); MemberLookup.resolveKind(); ExprResult CtorArg = SemaRef.BuildMemberReferenceExpr(MemberExprBase, ParamType, Loc, /*IsArrow=*/false, SS, /*TemplateKWLoc=*/SourceLocation(), /*FirstQualifierInScope=*/nullptr, MemberLookup, /*TemplateArgs=*/nullptr, /*S*/nullptr); if (CtorArg.isInvalid()) return true; // C++11 [class.copy]p15: // - if a member m has rvalue reference type T&&, it is direct-initialized // with static_cast(x.m); if (RefersToRValueRef(CtorArg.get())) { CtorArg = CastForMoving(SemaRef, CtorArg.get()); } InitializedEntity Entity = Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr, /*Implicit*/ true) : InitializedEntity::InitializeMember(Field, nullptr, /*Implicit*/ true); // Direct-initialize to use the copy constructor. InitializationKind InitKind = InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation()); Expr *CtorArgE = CtorArg.getAs(); InitializationSequence InitSeq(SemaRef, Entity, InitKind, CtorArgE); ExprResult MemberInit = InitSeq.Perform(SemaRef, Entity, InitKind, MultiExprArg(&CtorArgE, 1)); MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit); if (MemberInit.isInvalid()) return true; if (Indirect) CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer( SemaRef.Context, Indirect, Loc, Loc, MemberInit.getAs(), Loc); else CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer( SemaRef.Context, Field, Loc, Loc, MemberInit.getAs(), Loc); return false; } assert((ImplicitInitKind == IIK_Default || ImplicitInitKind == IIK_Inherit) && "Unhandled implicit init kind!"); QualType FieldBaseElementType = SemaRef.Context.getBaseElementType(Field->getType()); if (FieldBaseElementType->isRecordType()) { InitializedEntity InitEntity = Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr, /*Implicit*/ true) : InitializedEntity::InitializeMember(Field, nullptr, /*Implicit*/ true); InitializationKind InitKind = InitializationKind::CreateDefault(Loc); InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, None); ExprResult MemberInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, None); MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit); if (MemberInit.isInvalid()) return true; if (Indirect) CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect, Loc, Loc, MemberInit.get(), Loc); else CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field, Loc, Loc, MemberInit.get(), Loc); return false; } if (!Field->getParent()->isUnion()) { if (FieldBaseElementType->isReferenceType()) { SemaRef.Diag(Constructor->getLocation(), diag::err_uninitialized_member_in_ctor) << (int)Constructor->isImplicit() << SemaRef.Context.getTagDeclType(Constructor->getParent()) << 0 << Field->getDeclName(); SemaRef.Diag(Field->getLocation(), diag::note_declared_at); return true; } if (FieldBaseElementType.isConstQualified()) { SemaRef.Diag(Constructor->getLocation(), diag::err_uninitialized_member_in_ctor) << (int)Constructor->isImplicit() << SemaRef.Context.getTagDeclType(Constructor->getParent()) << 1 << Field->getDeclName(); SemaRef.Diag(Field->getLocation(), diag::note_declared_at); return true; } } if (FieldBaseElementType.hasNonTrivialObjCLifetime()) { // ARC and Weak: // Default-initialize Objective-C pointers to NULL. CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field, Loc, Loc, new (SemaRef.Context) ImplicitValueInitExpr(Field->getType()), Loc); return false; } // Nothing to initialize. CXXMemberInit = nullptr; return false; } namespace { struct BaseAndFieldInfo { Sema &S; CXXConstructorDecl *Ctor; bool AnyErrorsInInits; ImplicitInitializerKind IIK; llvm::DenseMap AllBaseFields; SmallVector AllToInit; llvm::DenseMap ActiveUnionMember; BaseAndFieldInfo(Sema &S, CXXConstructorDecl *Ctor, bool ErrorsInInits) : S(S), Ctor(Ctor), AnyErrorsInInits(ErrorsInInits) { bool Generated = Ctor->isImplicit() || Ctor->isDefaulted(); if (Ctor->getInheritedConstructor()) IIK = IIK_Inherit; else if (Generated && Ctor->isCopyConstructor()) IIK = IIK_Copy; else if (Generated && Ctor->isMoveConstructor()) IIK = IIK_Move; else IIK = IIK_Default; } bool isImplicitCopyOrMove() const { switch (IIK) { case IIK_Copy: case IIK_Move: return true; case IIK_Default: case IIK_Inherit: return false; } llvm_unreachable("Invalid ImplicitInitializerKind!"); } bool addFieldInitializer(CXXCtorInitializer *Init) { AllToInit.push_back(Init); // Check whether this initializer makes the field "used". if (Init->getInit()->HasSideEffects(S.Context)) S.UnusedPrivateFields.remove(Init->getAnyMember()); return false; } bool isInactiveUnionMember(FieldDecl *Field) { RecordDecl *Record = Field->getParent(); if (!Record->isUnion()) return false; if (FieldDecl *Active = ActiveUnionMember.lookup(Record->getCanonicalDecl())) return Active != Field->getCanonicalDecl(); // In an implicit copy or move constructor, ignore any in-class initializer. if (isImplicitCopyOrMove()) return true; // If there's no explicit initialization, the field is active only if it // has an in-class initializer... if (Field->hasInClassInitializer()) return false; // ... or it's an anonymous struct or union whose class has an in-class // initializer. if (!Field->isAnonymousStructOrUnion()) return true; CXXRecordDecl *FieldRD = Field->getType()->getAsCXXRecordDecl(); return !FieldRD->hasInClassInitializer(); } /// \brief Determine whether the given field is, or is within, a union member /// that is inactive (because there was an initializer given for a different /// member of the union, or because the union was not initialized at all). bool isWithinInactiveUnionMember(FieldDecl *Field, IndirectFieldDecl *Indirect) { if (!Indirect) return isInactiveUnionMember(Field); for (auto *C : Indirect->chain()) { FieldDecl *Field = dyn_cast(C); if (Field && isInactiveUnionMember(Field)) return true; } return false; } }; } /// \brief Determine whether the given type is an incomplete or zero-lenfgth /// array type. static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) { if (T->isIncompleteArrayType()) return true; while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) { if (!ArrayT->getSize()) return true; T = ArrayT->getElementType(); } return false; } static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, FieldDecl *Field, IndirectFieldDecl *Indirect = nullptr) { if (Field->isInvalidDecl()) return false; // Overwhelmingly common case: we have a direct initializer for this field. if (CXXCtorInitializer *Init = Info.AllBaseFields.lookup(Field->getCanonicalDecl())) return Info.addFieldInitializer(Init); // C++11 [class.base.init]p8: // if the entity is a non-static data member that has a // brace-or-equal-initializer and either // -- the constructor's class is a union and no other variant member of that // union is designated by a mem-initializer-id or // -- the constructor's class is not a union, and, if the entity is a member // of an anonymous union, no other member of that union is designated by // a mem-initializer-id, // the entity is initialized as specified in [dcl.init]. // // We also apply the same rules to handle anonymous structs within anonymous // unions. if (Info.isWithinInactiveUnionMember(Field, Indirect)) return false; if (Field->hasInClassInitializer() && !Info.isImplicitCopyOrMove()) { ExprResult DIE = SemaRef.BuildCXXDefaultInitExpr(Info.Ctor->getLocation(), Field); if (DIE.isInvalid()) return true; CXXCtorInitializer *Init; if (Indirect) Init = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect, SourceLocation(), SourceLocation(), DIE.get(), SourceLocation()); else Init = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field, SourceLocation(), SourceLocation(), DIE.get(), SourceLocation()); return Info.addFieldInitializer(Init); } // Don't initialize incomplete or zero-length arrays. if (isIncompleteOrZeroLengthArrayType(SemaRef.Context, Field->getType())) return false; // Don't try to build an implicit initializer if there were semantic // errors in any of the initializers (and therefore we might be // missing some that the user actually wrote). if (Info.AnyErrorsInInits) return false; CXXCtorInitializer *Init = nullptr; if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field, Indirect, Init)) return true; if (!Init) return false; return Info.addFieldInitializer(Init); } bool Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor, CXXCtorInitializer *Initializer) { assert(Initializer->isDelegatingInitializer()); Constructor->setNumCtorInitializers(1); CXXCtorInitializer **initializer = new (Context) CXXCtorInitializer*[1]; memcpy(initializer, &Initializer, sizeof (CXXCtorInitializer*)); Constructor->setCtorInitializers(initializer); if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) { MarkFunctionReferenced(Initializer->getSourceLocation(), Dtor); DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation()); } DelegatingCtorDecls.push_back(Constructor); DiagnoseUninitializedFields(*this, Constructor); return false; } bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors, ArrayRef Initializers) { if (Constructor->isDependentContext()) { // Just store the initializers as written, they will be checked during // instantiation. if (!Initializers.empty()) { Constructor->setNumCtorInitializers(Initializers.size()); CXXCtorInitializer **baseOrMemberInitializers = new (Context) CXXCtorInitializer*[Initializers.size()]; memcpy(baseOrMemberInitializers, Initializers.data(), Initializers.size() * sizeof(CXXCtorInitializer*)); Constructor->setCtorInitializers(baseOrMemberInitializers); } // Let template instantiation know whether we had errors. if (AnyErrors) Constructor->setInvalidDecl(); return false; } BaseAndFieldInfo Info(*this, Constructor, AnyErrors); // We need to build the initializer AST according to order of construction // and not what user specified in the Initializers list. CXXRecordDecl *ClassDecl = Constructor->getParent()->getDefinition(); if (!ClassDecl) return true; bool HadError = false; for (unsigned i = 0; i < Initializers.size(); i++) { CXXCtorInitializer *Member = Initializers[i]; if (Member->isBaseInitializer()) Info.AllBaseFields[Member->getBaseClass()->getAs()] = Member; else { Info.AllBaseFields[Member->getAnyMember()->getCanonicalDecl()] = Member; if (IndirectFieldDecl *F = Member->getIndirectMember()) { for (auto *C : F->chain()) { FieldDecl *FD = dyn_cast(C); if (FD && FD->getParent()->isUnion()) Info.ActiveUnionMember.insert(std::make_pair( FD->getParent()->getCanonicalDecl(), FD->getCanonicalDecl())); } } else if (FieldDecl *FD = Member->getMember()) { if (FD->getParent()->isUnion()) Info.ActiveUnionMember.insert(std::make_pair( FD->getParent()->getCanonicalDecl(), FD->getCanonicalDecl())); } } } // Keep track of the direct virtual bases. llvm::SmallPtrSet DirectVBases; for (auto &I : ClassDecl->bases()) { if (I.isVirtual()) DirectVBases.insert(&I); } // Push virtual bases before others. for (auto &VBase : ClassDecl->vbases()) { if (CXXCtorInitializer *Value = Info.AllBaseFields.lookup(VBase.getType()->getAs())) { // [class.base.init]p7, per DR257: // A mem-initializer where the mem-initializer-id names a virtual base // class is ignored during execution of a constructor of any class that // is not the most derived class. if (ClassDecl->isAbstract()) { // FIXME: Provide a fixit to remove the base specifier. This requires // tracking the location of the associated comma for a base specifier. Diag(Value->getSourceLocation(), diag::warn_abstract_vbase_init_ignored) << VBase.getType() << ClassDecl; DiagnoseAbstractType(ClassDecl); } Info.AllToInit.push_back(Value); } else if (!AnyErrors && !ClassDecl->isAbstract()) { // [class.base.init]p8, per DR257: // If a given [...] base class is not named by a mem-initializer-id // [...] and the entity is not a virtual base class of an abstract // class, then [...] the entity is default-initialized. bool IsInheritedVirtualBase = !DirectVBases.count(&VBase); CXXCtorInitializer *CXXBaseInit; if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK, &VBase, IsInheritedVirtualBase, CXXBaseInit)) { HadError = true; continue; } Info.AllToInit.push_back(CXXBaseInit); } } // Non-virtual bases. for (auto &Base : ClassDecl->bases()) { // Virtuals are in the virtual base list and already constructed. if (Base.isVirtual()) continue; if (CXXCtorInitializer *Value = Info.AllBaseFields.lookup(Base.getType()->getAs())) { Info.AllToInit.push_back(Value); } else if (!AnyErrors) { CXXCtorInitializer *CXXBaseInit; if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK, &Base, /*IsInheritedVirtualBase=*/false, CXXBaseInit)) { HadError = true; continue; } Info.AllToInit.push_back(CXXBaseInit); } } // Fields. for (auto *Mem : ClassDecl->decls()) { if (auto *F = dyn_cast(Mem)) { // C++ [class.bit]p2: // A declaration for a bit-field that omits the identifier declares an // unnamed bit-field. Unnamed bit-fields are not members and cannot be // initialized. if (F->isUnnamedBitfield()) continue; // If we're not generating the implicit copy/move constructor, then we'll // handle anonymous struct/union fields based on their individual // indirect fields. if (F->isAnonymousStructOrUnion() && !Info.isImplicitCopyOrMove()) continue; if (CollectFieldInitializer(*this, Info, F)) HadError = true; continue; } // Beyond this point, we only consider default initialization. if (Info.isImplicitCopyOrMove()) continue; if (auto *F = dyn_cast(Mem)) { if (F->getType()->isIncompleteArrayType()) { assert(ClassDecl->hasFlexibleArrayMember() && "Incomplete array type is not valid"); continue; } // Initialize each field of an anonymous struct individually. if (CollectFieldInitializer(*this, Info, F->getAnonField(), F)) HadError = true; continue; } } unsigned NumInitializers = Info.AllToInit.size(); if (NumInitializers > 0) { Constructor->setNumCtorInitializers(NumInitializers); CXXCtorInitializer **baseOrMemberInitializers = new (Context) CXXCtorInitializer*[NumInitializers]; memcpy(baseOrMemberInitializers, Info.AllToInit.data(), NumInitializers * sizeof(CXXCtorInitializer*)); Constructor->setCtorInitializers(baseOrMemberInitializers); // Constructors implicitly reference the base and member // destructors. MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(), Constructor->getParent()); } return HadError; } static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl &IdealInits) { if (const RecordType *RT = Field->getType()->getAs()) { const RecordDecl *RD = RT->getDecl(); if (RD->isAnonymousStructOrUnion()) { for (auto *Field : RD->fields()) PopulateKeysForFields(Field, IdealInits); return; } } IdealInits.push_back(Field->getCanonicalDecl()); } static const void *GetKeyForBase(ASTContext &Context, QualType BaseType) { return Context.getCanonicalType(BaseType).getTypePtr(); } static const void *GetKeyForMember(ASTContext &Context, CXXCtorInitializer *Member) { if (!Member->isAnyMemberInitializer()) return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0)); return Member->getAnyMember()->getCanonicalDecl(); } static void DiagnoseBaseOrMemInitializerOrder( Sema &SemaRef, const CXXConstructorDecl *Constructor, ArrayRef Inits) { if (Constructor->getDeclContext()->isDependentContext()) return; // Don't check initializers order unless the warning is enabled at the // location of at least one initializer. bool ShouldCheckOrder = false; for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) { CXXCtorInitializer *Init = Inits[InitIndex]; if (!SemaRef.Diags.isIgnored(diag::warn_initializer_out_of_order, Init->getSourceLocation())) { ShouldCheckOrder = true; break; } } if (!ShouldCheckOrder) return; // Build the list of bases and members in the order that they'll // actually be initialized. The explicit initializers should be in // this same order but may be missing things. SmallVector IdealInitKeys; const CXXRecordDecl *ClassDecl = Constructor->getParent(); // 1. Virtual bases. for (const auto &VBase : ClassDecl->vbases()) IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, VBase.getType())); // 2. Non-virtual bases. for (const auto &Base : ClassDecl->bases()) { if (Base.isVirtual()) continue; IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, Base.getType())); } // 3. Direct fields. for (auto *Field : ClassDecl->fields()) { if (Field->isUnnamedBitfield()) continue; PopulateKeysForFields(Field, IdealInitKeys); } unsigned NumIdealInits = IdealInitKeys.size(); unsigned IdealIndex = 0; CXXCtorInitializer *PrevInit = nullptr; for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) { CXXCtorInitializer *Init = Inits[InitIndex]; const void *InitKey = GetKeyForMember(SemaRef.Context, Init); // Scan forward to try to find this initializer in the idealized // initializers list. for (; IdealIndex != NumIdealInits; ++IdealIndex) if (InitKey == IdealInitKeys[IdealIndex]) break; // If we didn't find this initializer, it must be because we // scanned past it on a previous iteration. That can only // happen if we're out of order; emit a warning. if (IdealIndex == NumIdealInits && PrevInit) { Sema::SemaDiagnosticBuilder D = SemaRef.Diag(PrevInit->getSourceLocation(), diag::warn_initializer_out_of_order); if (PrevInit->isAnyMemberInitializer()) D << 0 << PrevInit->getAnyMember()->getDeclName(); else D << 1 << PrevInit->getTypeSourceInfo()->getType(); if (Init->isAnyMemberInitializer()) D << 0 << Init->getAnyMember()->getDeclName(); else D << 1 << Init->getTypeSourceInfo()->getType(); // Move back to the initializer's location in the ideal list. for (IdealIndex = 0; IdealIndex != NumIdealInits; ++IdealIndex) if (InitKey == IdealInitKeys[IdealIndex]) break; assert(IdealIndex < NumIdealInits && "initializer not found in initializer list"); } PrevInit = Init; } } namespace { bool CheckRedundantInit(Sema &S, CXXCtorInitializer *Init, CXXCtorInitializer *&PrevInit) { if (!PrevInit) { PrevInit = Init; return false; } if (FieldDecl *Field = Init->getAnyMember()) S.Diag(Init->getSourceLocation(), diag::err_multiple_mem_initialization) << Field->getDeclName() << Init->getSourceRange(); else { const Type *BaseClass = Init->getBaseClass(); assert(BaseClass && "neither field nor base"); S.Diag(Init->getSourceLocation(), diag::err_multiple_base_initialization) << QualType(BaseClass, 0) << Init->getSourceRange(); } S.Diag(PrevInit->getSourceLocation(), diag::note_previous_initializer) << 0 << PrevInit->getSourceRange(); return true; } typedef std::pair UnionEntry; typedef llvm::DenseMap RedundantUnionMap; bool CheckRedundantUnionInit(Sema &S, CXXCtorInitializer *Init, RedundantUnionMap &Unions) { FieldDecl *Field = Init->getAnyMember(); RecordDecl *Parent = Field->getParent(); NamedDecl *Child = Field; while (Parent->isAnonymousStructOrUnion() || Parent->isUnion()) { if (Parent->isUnion()) { UnionEntry &En = Unions[Parent]; if (En.first && En.first != Child) { S.Diag(Init->getSourceLocation(), diag::err_multiple_mem_union_initialization) << Field->getDeclName() << Init->getSourceRange(); S.Diag(En.second->getSourceLocation(), diag::note_previous_initializer) << 0 << En.second->getSourceRange(); return true; } if (!En.first) { En.first = Child; En.second = Init; } if (!Parent->isAnonymousStructOrUnion()) return false; } Child = Parent; Parent = cast(Parent->getDeclContext()); } return false; } } /// ActOnMemInitializers - Handle the member initializers for a constructor. void Sema::ActOnMemInitializers(Decl *ConstructorDecl, SourceLocation ColonLoc, ArrayRef MemInits, bool AnyErrors) { if (!ConstructorDecl) return; AdjustDeclIfTemplate(ConstructorDecl); CXXConstructorDecl *Constructor = dyn_cast(ConstructorDecl); if (!Constructor) { Diag(ColonLoc, diag::err_only_constructors_take_base_inits); return; } // Mapping for the duplicate initializers check. // For member initializers, this is keyed with a FieldDecl*. // For base initializers, this is keyed with a Type*. llvm::DenseMap Members; // Mapping for the inconsistent anonymous-union initializers check. RedundantUnionMap MemberUnions; bool HadError = false; for (unsigned i = 0; i < MemInits.size(); i++) { CXXCtorInitializer *Init = MemInits[i]; // Set the source order index. Init->setSourceOrder(i); if (Init->isAnyMemberInitializer()) { const void *Key = GetKeyForMember(Context, Init); if (CheckRedundantInit(*this, Init, Members[Key]) || CheckRedundantUnionInit(*this, Init, MemberUnions)) HadError = true; } else if (Init->isBaseInitializer()) { const void *Key = GetKeyForMember(Context, Init); if (CheckRedundantInit(*this, Init, Members[Key])) HadError = true; } else { assert(Init->isDelegatingInitializer()); // This must be the only initializer if (MemInits.size() != 1) { Diag(Init->getSourceLocation(), diag::err_delegating_initializer_alone) << Init->getSourceRange() << MemInits[i ? 0 : 1]->getSourceRange(); // We will treat this as being the only initializer. } SetDelegatingInitializer(Constructor, MemInits[i]); // Return immediately as the initializer is set. return; } } if (HadError) return; DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits); SetCtorInitializers(Constructor, AnyErrors, MemInits); DiagnoseUninitializedFields(*this, Constructor); } void Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, CXXRecordDecl *ClassDecl) { // Ignore dependent contexts. Also ignore unions, since their members never // have destructors implicitly called. if (ClassDecl->isDependentContext() || ClassDecl->isUnion()) return; // FIXME: all the access-control diagnostics are positioned on the // field/base declaration. That's probably good; that said, the // user might reasonably want to know why the destructor is being // emitted, and we currently don't say. // Non-static data members. for (auto *Field : ClassDecl->fields()) { if (Field->isInvalidDecl()) continue; // Don't destroy incomplete or zero-length arrays. if (isIncompleteOrZeroLengthArrayType(Context, Field->getType())) continue; QualType FieldType = Context.getBaseElementType(Field->getType()); const RecordType* RT = FieldType->getAs(); if (!RT) continue; CXXRecordDecl *FieldClassDecl = cast(RT->getDecl()); if (FieldClassDecl->isInvalidDecl()) continue; if (FieldClassDecl->hasIrrelevantDestructor()) continue; // The destructor for an implicit anonymous union member is never invoked. if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion()) continue; CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl); assert(Dtor && "No dtor found for FieldClassDecl!"); CheckDestructorAccess(Field->getLocation(), Dtor, PDiag(diag::err_access_dtor_field) << Field->getDeclName() << FieldType); MarkFunctionReferenced(Location, Dtor); DiagnoseUseOfDecl(Dtor, Location); } // We only potentially invoke the destructors of potentially constructed // subobjects. bool VisitVirtualBases = !ClassDecl->isAbstract(); llvm::SmallPtrSet DirectVirtualBases; // Bases. for (const auto &Base : ClassDecl->bases()) { // Bases are always records in a well-formed non-dependent class. const RecordType *RT = Base.getType()->getAs(); // Remember direct virtual bases. if (Base.isVirtual()) { if (!VisitVirtualBases) continue; DirectVirtualBases.insert(RT); } CXXRecordDecl *BaseClassDecl = cast(RT->getDecl()); // If our base class is invalid, we probably can't get its dtor anyway. if (BaseClassDecl->isInvalidDecl()) continue; if (BaseClassDecl->hasIrrelevantDestructor()) continue; CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); assert(Dtor && "No dtor found for BaseClassDecl!"); // FIXME: caret should be on the start of the class name CheckDestructorAccess(Base.getLocStart(), Dtor, PDiag(diag::err_access_dtor_base) << Base.getType() << Base.getSourceRange(), Context.getTypeDeclType(ClassDecl)); MarkFunctionReferenced(Location, Dtor); DiagnoseUseOfDecl(Dtor, Location); } if (!VisitVirtualBases) return; // Virtual bases. for (const auto &VBase : ClassDecl->vbases()) { // Bases are always records in a well-formed non-dependent class. const RecordType *RT = VBase.getType()->castAs(); // Ignore direct virtual bases. if (DirectVirtualBases.count(RT)) continue; CXXRecordDecl *BaseClassDecl = cast(RT->getDecl()); // If our base class is invalid, we probably can't get its dtor anyway. if (BaseClassDecl->isInvalidDecl()) continue; if (BaseClassDecl->hasIrrelevantDestructor()) continue; CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); assert(Dtor && "No dtor found for BaseClassDecl!"); if (CheckDestructorAccess( ClassDecl->getLocation(), Dtor, PDiag(diag::err_access_dtor_vbase) << Context.getTypeDeclType(ClassDecl) << VBase.getType(), Context.getTypeDeclType(ClassDecl)) == AR_accessible) { CheckDerivedToBaseConversion( Context.getTypeDeclType(ClassDecl), VBase.getType(), diag::err_access_dtor_vbase, 0, ClassDecl->getLocation(), SourceRange(), DeclarationName(), nullptr); } MarkFunctionReferenced(Location, Dtor); DiagnoseUseOfDecl(Dtor, Location); } } void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) { if (!CDtorDecl) return; if (CXXConstructorDecl *Constructor = dyn_cast(CDtorDecl)) { SetCtorInitializers(Constructor, /*AnyErrors=*/false); DiagnoseUninitializedFields(*this, Constructor); } } bool Sema::isAbstractType(SourceLocation Loc, QualType T) { if (!getLangOpts().CPlusPlus) return false; const auto *RD = Context.getBaseElementType(T)->getAsCXXRecordDecl(); if (!RD) return false; // FIXME: Per [temp.inst]p1, we are supposed to trigger instantiation of a // class template specialization here, but doing so breaks a lot of code. // We can't answer whether something is abstract until it has a // definition. If it's currently being defined, we'll walk back // over all the declarations when we have a full definition. const CXXRecordDecl *Def = RD->getDefinition(); if (!Def || Def->isBeingDefined()) return false; return RD->isAbstract(); } bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, TypeDiagnoser &Diagnoser) { if (!isAbstractType(Loc, T)) return false; T = Context.getBaseElementType(T); Diagnoser.diagnose(*this, Loc, T); DiagnoseAbstractType(T->getAsCXXRecordDecl()); return true; } void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) { // Check if we've already emitted the list of pure virtual functions // for this class. if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD)) return; // If the diagnostic is suppressed, don't emit the notes. We're only // going to emit them once, so try to attach them to a diagnostic we're // actually going to show. if (Diags.isLastDiagnosticIgnored()) return; CXXFinalOverriderMap FinalOverriders; RD->getFinalOverriders(FinalOverriders); // Keep a set of seen pure methods so we won't diagnose the same method // more than once. llvm::SmallPtrSet SeenPureMethods; for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(), MEnd = FinalOverriders.end(); M != MEnd; ++M) { for (OverridingMethods::iterator SO = M->second.begin(), SOEnd = M->second.end(); SO != SOEnd; ++SO) { // C++ [class.abstract]p4: // A class is abstract if it contains or inherits at least one // pure virtual function for which the final overrider is pure // virtual. // if (SO->second.size() != 1) continue; if (!SO->second.front().Method->isPure()) continue; if (!SeenPureMethods.insert(SO->second.front().Method).second) continue; Diag(SO->second.front().Method->getLocation(), diag::note_pure_virtual_function) << SO->second.front().Method->getDeclName() << RD->getDeclName(); } } if (!PureVirtualClassDiagSet) PureVirtualClassDiagSet.reset(new RecordDeclSetTy); PureVirtualClassDiagSet->insert(RD); } namespace { struct AbstractUsageInfo { Sema &S; CXXRecordDecl *Record; CanQualType AbstractType; bool Invalid; AbstractUsageInfo(Sema &S, CXXRecordDecl *Record) : S(S), Record(Record), AbstractType(S.Context.getCanonicalType( S.Context.getTypeDeclType(Record))), Invalid(false) {} void DiagnoseAbstractType() { if (Invalid) return; S.DiagnoseAbstractType(Record); Invalid = true; } void CheckType(const NamedDecl *D, TypeLoc TL, Sema::AbstractDiagSelID Sel); }; struct CheckAbstractUsage { AbstractUsageInfo &Info; const NamedDecl *Ctx; CheckAbstractUsage(AbstractUsageInfo &Info, const NamedDecl *Ctx) : Info(Info), Ctx(Ctx) {} void Visit(TypeLoc TL, Sema::AbstractDiagSelID Sel) { switch (TL.getTypeLocClass()) { #define ABSTRACT_TYPELOC(CLASS, PARENT) #define TYPELOC(CLASS, PARENT) \ case TypeLoc::CLASS: Check(TL.castAs(), Sel); break; #include "clang/AST/TypeLocNodes.def" } } void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) { Visit(TL.getReturnLoc(), Sema::AbstractReturnType); for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) { if (!TL.getParam(I)) continue; TypeSourceInfo *TSI = TL.getParam(I)->getTypeSourceInfo(); if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType); } } void Check(ArrayTypeLoc TL, Sema::AbstractDiagSelID Sel) { Visit(TL.getElementLoc(), Sema::AbstractArrayType); } void Check(TemplateSpecializationTypeLoc TL, Sema::AbstractDiagSelID Sel) { // Visit the type parameters from a permissive context. for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { TemplateArgumentLoc TAL = TL.getArgLoc(I); if (TAL.getArgument().getKind() == TemplateArgument::Type) if (TypeSourceInfo *TSI = TAL.getTypeSourceInfo()) Visit(TSI->getTypeLoc(), Sema::AbstractNone); // TODO: other template argument types? } } // Visit pointee types from a permissive context. #define CheckPolymorphic(Type) \ void Check(Type TL, Sema::AbstractDiagSelID Sel) { \ Visit(TL.getNextTypeLoc(), Sema::AbstractNone); \ } CheckPolymorphic(PointerTypeLoc) CheckPolymorphic(ReferenceTypeLoc) CheckPolymorphic(MemberPointerTypeLoc) CheckPolymorphic(BlockPointerTypeLoc) CheckPolymorphic(AtomicTypeLoc) /// Handle all the types we haven't given a more specific /// implementation for above. void Check(TypeLoc TL, Sema::AbstractDiagSelID Sel) { // Every other kind of type that we haven't called out already // that has an inner type is either (1) sugar or (2) contains that // inner type in some way as a subobject. if (TypeLoc Next = TL.getNextTypeLoc()) return Visit(Next, Sel); // If there's no inner type and we're in a permissive context, // don't diagnose. if (Sel == Sema::AbstractNone) return; // Check whether the type matches the abstract type. QualType T = TL.getType(); if (T->isArrayType()) { Sel = Sema::AbstractArrayType; T = Info.S.Context.getBaseElementType(T); } CanQualType CT = T->getCanonicalTypeUnqualified().getUnqualifiedType(); if (CT != Info.AbstractType) return; // It matched; do some magic. if (Sel == Sema::AbstractArrayType) { Info.S.Diag(Ctx->getLocation(), diag::err_array_of_abstract_type) << T << TL.getSourceRange(); } else { Info.S.Diag(Ctx->getLocation(), diag::err_abstract_type_in_decl) << Sel << T << TL.getSourceRange(); } Info.DiagnoseAbstractType(); } }; void AbstractUsageInfo::CheckType(const NamedDecl *D, TypeLoc TL, Sema::AbstractDiagSelID Sel) { CheckAbstractUsage(*this, D).Visit(TL, Sel); } } /// Check for invalid uses of an abstract type in a method declaration. static void CheckAbstractClassUsage(AbstractUsageInfo &Info, CXXMethodDecl *MD) { // No need to do the check on definitions, which require that // the return/param types be complete. if (MD->doesThisDeclarationHaveABody()) return; // For safety's sake, just ignore it if we don't have type source // information. This should never happen for non-implicit methods, // but... if (TypeSourceInfo *TSI = MD->getTypeSourceInfo()) Info.CheckType(MD, TSI->getTypeLoc(), Sema::AbstractNone); } /// Check for invalid uses of an abstract type within a class definition. static void CheckAbstractClassUsage(AbstractUsageInfo &Info, CXXRecordDecl *RD) { for (auto *D : RD->decls()) { if (D->isImplicit()) continue; // Methods and method templates. if (isa(D)) { CheckAbstractClassUsage(Info, cast(D)); } else if (isa(D)) { FunctionDecl *FD = cast(D)->getTemplatedDecl(); CheckAbstractClassUsage(Info, cast(FD)); // Fields and static variables. } else if (isa(D)) { FieldDecl *FD = cast(D); if (TypeSourceInfo *TSI = FD->getTypeSourceInfo()) Info.CheckType(FD, TSI->getTypeLoc(), Sema::AbstractFieldType); } else if (isa(D)) { VarDecl *VD = cast(D); if (TypeSourceInfo *TSI = VD->getTypeSourceInfo()) Info.CheckType(VD, TSI->getTypeLoc(), Sema::AbstractVariableType); // Nested classes and class templates. } else if (isa(D)) { CheckAbstractClassUsage(Info, cast(D)); } else if (isa(D)) { CheckAbstractClassUsage(Info, cast(D)->getTemplatedDecl()); } } } static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); if (!ClassAttr) return; assert(ClassAttr->getKind() == attr::DLLExport); TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind(); if (TSK == TSK_ExplicitInstantiationDeclaration) // Don't go any further if this is just an explicit instantiation // declaration. return; for (Decl *Member : Class->decls()) { auto *MD = dyn_cast(Member); if (!MD) continue; if (Member->getAttr()) { if (MD->isUserProvided()) { // Instantiate non-default class member functions ... // .. except for certain kinds of template specializations. if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited()) continue; S.MarkFunctionReferenced(Class->getLocation(), MD); // The function will be passed to the consumer when its definition is // encountered. } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() || MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()) { // Synthesize and instantiate non-trivial implicit methods, explicitly // defaulted methods, and the copy and move assignment operators. The // latter are exported even if they are trivial, because the address of // an operator can be taken and should compare equal across libraries. DiagnosticErrorTrap Trap(S.Diags); S.MarkFunctionReferenced(Class->getLocation(), MD); if (Trap.hasErrorOccurred()) { S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class) << Class->getName() << !S.getLangOpts().CPlusPlus11; break; } // There is no later point when we will see the definition of this // function, so pass it to the consumer now. S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); } } } } static void checkForMultipleExportedDefaultConstructors(Sema &S, CXXRecordDecl *Class) { // Only the MS ABI has default constructor closures, so we don't need to do // this semantic checking anywhere else. if (!S.Context.getTargetInfo().getCXXABI().isMicrosoft()) return; CXXConstructorDecl *LastExportedDefaultCtor = nullptr; for (Decl *Member : Class->decls()) { // Look for exported default constructors. auto *CD = dyn_cast(Member); if (!CD || !CD->isDefaultConstructor()) continue; auto *Attr = CD->getAttr(); if (!Attr) continue; // If the class is non-dependent, mark the default arguments as ODR-used so // that we can properly codegen the constructor closure. if (!Class->isDependentContext()) { for (ParmVarDecl *PD : CD->parameters()) { (void)S.CheckCXXDefaultArgExpr(Attr->getLocation(), CD, PD); S.DiscardCleanupsInEvaluationContext(); } } if (LastExportedDefaultCtor) { S.Diag(LastExportedDefaultCtor->getLocation(), diag::err_attribute_dll_ambiguous_default_ctor) << Class; S.Diag(CD->getLocation(), diag::note_entity_declared_at) << CD->getDeclName(); return; } LastExportedDefaultCtor = CD; } } /// \brief Check class-level dllimport/dllexport attribute. void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); // MSVC inherits DLL attributes to partial class template specializations. if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) { if (auto *Spec = dyn_cast(Class)) { if (Attr *TemplateAttr = getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) { auto *A = cast(TemplateAttr->clone(getASTContext())); A->setInherited(true); ClassAttr = A; } } } if (!ClassAttr) return; if (!Class->isExternallyVisible()) { Diag(Class->getLocation(), diag::err_attribute_dll_not_extern) << Class << ClassAttr; return; } if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr->isInherited()) { // Diagnose dll attributes on members of class with dll attribute. for (Decl *Member : Class->decls()) { if (!isa(Member) && !isa(Member)) continue; InheritableAttr *MemberAttr = getDLLAttr(Member); if (!MemberAttr || MemberAttr->isInherited() || Member->isInvalidDecl()) continue; Diag(MemberAttr->getLocation(), diag::err_attribute_dll_member_of_dll_class) << MemberAttr << ClassAttr; Diag(ClassAttr->getLocation(), diag::note_previous_attribute); Member->setInvalidDecl(); } } if (Class->getDescribedClassTemplate()) // Don't inherit dll attribute until the template is instantiated. return; // The class is either imported or exported. const bool ClassExported = ClassAttr->getKind() == attr::DLLExport; TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind(); // Ignore explicit dllexport on explicit class template instantiation declarations. if (ClassExported && !ClassAttr->isInherited() && TSK == TSK_ExplicitInstantiationDeclaration) { Class->dropAttr(); return; } // Force declaration of implicit members so they can inherit the attribute. ForceDeclarationOfImplicitMembers(Class); // FIXME: MSVC's docs say all bases must be exportable, but this doesn't // seem to be true in practice? for (Decl *Member : Class->decls()) { VarDecl *VD = dyn_cast(Member); CXXMethodDecl *MD = dyn_cast(Member); // Only methods and static fields inherit the attributes. if (!VD && !MD) continue; if (MD) { // Don't process deleted methods. if (MD->isDeleted()) continue; if (MD->isInlined()) { // MinGW does not import or export inline methods. if (!Context.getTargetInfo().getCXXABI().isMicrosoft() && !Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) continue; // MSVC versions before 2015 don't export the move assignment operators // and move constructor, so don't attempt to import/export them if // we have a definition. auto *Ctor = dyn_cast(MD); if ((MD->isMoveAssignmentOperator() || (Ctor && Ctor->isMoveConstructor())) && !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015)) continue; // MSVC2015 doesn't export trivial defaulted x-tor but copy assign // operator is exported anyway. if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) && (Ctor || isa(MD)) && MD->isTrivial()) continue; } } if (!cast(Member)->isExternallyVisible()) continue; if (!getDLLAttr(Member)) { auto *NewAttr = cast(ClassAttr->clone(getASTContext())); NewAttr->setInherited(true); Member->addAttr(NewAttr); } } if (ClassExported) DelayedDllExportClasses.push_back(Class); } /// \brief Perform propagation of DLL attributes from a derived class to a /// templated base class for MS compatibility. void Sema::propagateDLLAttrToBaseClassTemplate( CXXRecordDecl *Class, Attr *ClassAttr, ClassTemplateSpecializationDecl *BaseTemplateSpec, SourceLocation BaseLoc) { if (getDLLAttr( BaseTemplateSpec->getSpecializedTemplate()->getTemplatedDecl())) { // If the base class template has a DLL attribute, don't try to change it. return; } auto TSK = BaseTemplateSpec->getSpecializationKind(); if (!getDLLAttr(BaseTemplateSpec) && (TSK == TSK_Undeclared || TSK == TSK_ExplicitInstantiationDeclaration || TSK == TSK_ImplicitInstantiation)) { // The template hasn't been instantiated yet (or it has, but only as an // explicit instantiation declaration or implicit instantiation, which means // we haven't codegenned any members yet), so propagate the attribute. auto *NewAttr = cast(ClassAttr->clone(getASTContext())); NewAttr->setInherited(true); BaseTemplateSpec->addAttr(NewAttr); // If the template is already instantiated, checkDLLAttributeRedeclaration() // needs to be run again to work see the new attribute. Otherwise this will // get run whenever the template is instantiated. if (TSK != TSK_Undeclared) checkClassLevelDLLAttribute(BaseTemplateSpec); return; } if (getDLLAttr(BaseTemplateSpec)) { // The template has already been specialized or instantiated with an // attribute, explicitly or through propagation. We should not try to change // it. return; } // The template was previously instantiated or explicitly specialized without // a dll attribute, It's too late for us to add an attribute, so warn that // this is unsupported. Diag(BaseLoc, diag::warn_attribute_dll_instantiated_base_class) << BaseTemplateSpec->isExplicitSpecialization(); Diag(ClassAttr->getLocation(), diag::note_attribute); if (BaseTemplateSpec->isExplicitSpecialization()) { Diag(BaseTemplateSpec->getLocation(), diag::note_template_class_explicit_specialization_was_here) << BaseTemplateSpec; } else { Diag(BaseTemplateSpec->getPointOfInstantiation(), diag::note_template_class_instantiation_was_here) << BaseTemplateSpec; } } static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD, SourceLocation DefaultLoc) { switch (S.getSpecialMember(MD)) { case Sema::CXXDefaultConstructor: S.DefineImplicitDefaultConstructor(DefaultLoc, cast(MD)); break; case Sema::CXXCopyConstructor: S.DefineImplicitCopyConstructor(DefaultLoc, cast(MD)); break; case Sema::CXXCopyAssignment: S.DefineImplicitCopyAssignment(DefaultLoc, MD); break; case Sema::CXXDestructor: S.DefineImplicitDestructor(DefaultLoc, cast(MD)); break; case Sema::CXXMoveConstructor: S.DefineImplicitMoveConstructor(DefaultLoc, cast(MD)); break; case Sema::CXXMoveAssignment: S.DefineImplicitMoveAssignment(DefaultLoc, MD); break; case Sema::CXXInvalid: llvm_unreachable("Invalid special member."); } } /// Determine whether a type is permitted to be passed or returned in /// registers, per C++ [class.temporary]p3. static bool computeCanPassInRegisters(Sema &S, CXXRecordDecl *D) { if (D->isDependentType() || D->isInvalidDecl()) return false; // Per C++ [class.temporary]p3, the relevant condition is: // each copy constructor, move constructor, and destructor of X is // either trivial or deleted, and X has at least one non-deleted copy // or move constructor bool HasNonDeletedCopyOrMove = false; if (D->needsImplicitCopyConstructor() && !D->defaultedCopyConstructorIsDeleted()) { if (!D->hasTrivialCopyConstructor()) return false; HasNonDeletedCopyOrMove = true; } if (S.getLangOpts().CPlusPlus11 && D->needsImplicitMoveConstructor() && !D->defaultedMoveConstructorIsDeleted()) { if (!D->hasTrivialMoveConstructor()) return false; HasNonDeletedCopyOrMove = true; } if (D->needsImplicitDestructor() && !D->defaultedDestructorIsDeleted() && !D->hasTrivialDestructor()) return false; for (const CXXMethodDecl *MD : D->methods()) { if (MD->isDeleted()) continue; auto *CD = dyn_cast(MD); if (CD && CD->isCopyOrMoveConstructor()) HasNonDeletedCopyOrMove = true; else if (!isa(MD)) continue; if (!MD->isTrivial()) return false; } return HasNonDeletedCopyOrMove; } /// \brief Perform semantic checks on a class definition that has been /// completing, introducing implicitly-declared members, checking for /// abstract types, etc. void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { if (!Record) return; if (Record->isAbstract() && !Record->isInvalidDecl()) { AbstractUsageInfo Info(*this, Record); CheckAbstractClassUsage(Info, Record); } // If this is not an aggregate type and has no user-declared constructor, // complain about any non-static data members of reference or const scalar // type, since they will never get initializers. if (!Record->isInvalidDecl() && !Record->isDependentType() && !Record->isAggregate() && !Record->hasUserDeclaredConstructor() && !Record->isLambda()) { bool Complained = false; for (const auto *F : Record->fields()) { if (F->hasInClassInitializer() || F->isUnnamedBitfield()) continue; if (F->getType()->isReferenceType() || (F->getType().isConstQualified() && F->getType()->isScalarType())) { if (!Complained) { Diag(Record->getLocation(), diag::warn_no_constructor_for_refconst) << Record->getTagKind() << Record; Complained = true; } Diag(F->getLocation(), diag::note_refconst_member_not_initialized) << F->getType()->isReferenceType() << F->getDeclName(); } } } if (Record->getIdentifier()) { // C++ [class.mem]p13: // If T is the name of a class, then each of the following shall have a // name different from T: // - every member of every anonymous union that is a member of class T. // // C++ [class.mem]p14: // In addition, if class T has a user-declared constructor (12.1), every // non-static data member of class T shall have a name different from T. DeclContext::lookup_result R = Record->lookup(Record->getDeclName()); for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { NamedDecl *D = *I; if ((isa(D) && Record->hasUserDeclaredConstructor()) || isa(D)) { Diag(D->getLocation(), diag::err_member_name_of_class) << D->getDeclName(); break; } } } // Warn if the class has virtual methods but non-virtual public destructor. if (Record->isPolymorphic() && !Record->isDependentType()) { CXXDestructorDecl *dtor = Record->getDestructor(); if ((!dtor || (!dtor->isVirtual() && dtor->getAccess() == AS_public)) && !Record->hasAttr()) Diag(dtor ? dtor->getLocation() : Record->getLocation(), diag::warn_non_virtual_dtor) << Context.getRecordType(Record); } if (Record->isAbstract()) { if (FinalAttr *FA = Record->getAttr()) { Diag(Record->getLocation(), diag::warn_abstract_final_class) << FA->isSpelledAsSealed(); DiagnoseAbstractType(Record); } } bool HasMethodWithOverrideControl = false, HasOverridingMethodWithoutOverrideControl = false; if (!Record->isDependentType()) { for (auto *M : Record->methods()) { // See if a method overloads virtual methods in a base // class without overriding any. if (!M->isStatic()) DiagnoseHiddenVirtualMethods(M); if (M->hasAttr()) HasMethodWithOverrideControl = true; else if (M->size_overridden_methods() > 0) HasOverridingMethodWithoutOverrideControl = true; // Check whether the explicitly-defaulted special members are valid. if (!M->isInvalidDecl() && M->isExplicitlyDefaulted()) CheckExplicitlyDefaultedSpecialMember(M); // For an explicitly defaulted or deleted special member, we defer // determining triviality until the class is complete. That time is now! CXXSpecialMember CSM = getSpecialMember(M); if (!M->isImplicit() && !M->isUserProvided()) { if (CSM != CXXInvalid) { M->setTrivial(SpecialMemberIsTrivial(M, CSM)); // Inform the class that we've finished declaring this member. Record->finishedDefaultedOrDeletedMember(M); } } if (!M->isInvalidDecl() && M->isExplicitlyDefaulted() && M->hasAttr()) { if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) && M->isTrivial() && (CSM == CXXDefaultConstructor || CSM == CXXCopyConstructor || CSM == CXXDestructor)) M->dropAttr(); if (M->hasAttr()) { DefineImplicitSpecialMember(*this, M, M->getLocation()); ActOnFinishInlineFunctionDef(M); } } } } if (HasMethodWithOverrideControl && HasOverridingMethodWithoutOverrideControl) { // At least one method has the 'override' control declared. // Diagnose all other overridden methods which do not have 'override' specified on them. for (auto *M : Record->methods()) DiagnoseAbsenceOfOverrideControl(M); } // ms_struct is a request to use the same ABI rules as MSVC. Check // whether this class uses any C++ features that are implemented // completely differently in MSVC, and if so, emit a diagnostic. // That diagnostic defaults to an error, but we allow projects to // map it down to a warning (or ignore it). It's a fairly common // practice among users of the ms_struct pragma to mass-annotate // headers, sweeping up a bunch of types that the project doesn't // really rely on MSVC-compatible layout for. We must therefore // support "ms_struct except for C++ stuff" as a secondary ABI. if (Record->isMsStruct(Context) && (Record->isPolymorphic() || Record->getNumBases())) { Diag(Record->getLocation(), diag::warn_cxx_ms_struct); } checkClassLevelDLLAttribute(Record); Record->setCanPassInRegisters(computeCanPassInRegisters(*this, Record)); } /// Look up the special member function that would be called by a special /// member function for a subobject of class type. /// /// \param Class The class type of the subobject. /// \param CSM The kind of special member function. /// \param FieldQuals If the subobject is a field, its cv-qualifiers. /// \param ConstRHS True if this is a copy operation with a const object /// on its RHS, that is, if the argument to the outer special member /// function is 'const' and this is not a field marked 'mutable'. static Sema::SpecialMemberOverloadResult lookupCallFromSpecialMember( Sema &S, CXXRecordDecl *Class, Sema::CXXSpecialMember CSM, unsigned FieldQuals, bool ConstRHS) { unsigned LHSQuals = 0; if (CSM == Sema::CXXCopyAssignment || CSM == Sema::CXXMoveAssignment) LHSQuals = FieldQuals; unsigned RHSQuals = FieldQuals; if (CSM == Sema::CXXDefaultConstructor || CSM == Sema::CXXDestructor) RHSQuals = 0; else if (ConstRHS) RHSQuals |= Qualifiers::Const; return S.LookupSpecialMember(Class, CSM, RHSQuals & Qualifiers::Const, RHSQuals & Qualifiers::Volatile, false, LHSQuals & Qualifiers::Const, LHSQuals & Qualifiers::Volatile); } class Sema::InheritedConstructorInfo { Sema &S; SourceLocation UseLoc; /// A mapping from the base classes through which the constructor was /// inherited to the using shadow declaration in that base class (or a null /// pointer if the constructor was declared in that base class). llvm::DenseMap InheritedFromBases; public: InheritedConstructorInfo(Sema &S, SourceLocation UseLoc, ConstructorUsingShadowDecl *Shadow) : S(S), UseLoc(UseLoc) { bool DiagnosedMultipleConstructedBases = false; CXXRecordDecl *ConstructedBase = nullptr; UsingDecl *ConstructedBaseUsing = nullptr; // Find the set of such base class subobjects and check that there's a // unique constructed subobject. for (auto *D : Shadow->redecls()) { auto *DShadow = cast(D); auto *DNominatedBase = DShadow->getNominatedBaseClass(); auto *DConstructedBase = DShadow->getConstructedBaseClass(); InheritedFromBases.insert( std::make_pair(DNominatedBase->getCanonicalDecl(), DShadow->getNominatedBaseClassShadowDecl())); if (DShadow->constructsVirtualBase()) InheritedFromBases.insert( std::make_pair(DConstructedBase->getCanonicalDecl(), DShadow->getConstructedBaseClassShadowDecl())); else assert(DNominatedBase == DConstructedBase); // [class.inhctor.init]p2: // If the constructor was inherited from multiple base class subobjects // of type B, the program is ill-formed. if (!ConstructedBase) { ConstructedBase = DConstructedBase; ConstructedBaseUsing = D->getUsingDecl(); } else if (ConstructedBase != DConstructedBase && !Shadow->isInvalidDecl()) { if (!DiagnosedMultipleConstructedBases) { S.Diag(UseLoc, diag::err_ambiguous_inherited_constructor) << Shadow->getTargetDecl(); S.Diag(ConstructedBaseUsing->getLocation(), diag::note_ambiguous_inherited_constructor_using) << ConstructedBase; DiagnosedMultipleConstructedBases = true; } S.Diag(D->getUsingDecl()->getLocation(), diag::note_ambiguous_inherited_constructor_using) << DConstructedBase; } } if (DiagnosedMultipleConstructedBases) Shadow->setInvalidDecl(); } /// Find the constructor to use for inherited construction of a base class, /// and whether that base class constructor inherits the constructor from a /// virtual base class (in which case it won't actually invoke it). std::pair findConstructorForBase(CXXRecordDecl *Base, CXXConstructorDecl *Ctor) const { auto It = InheritedFromBases.find(Base->getCanonicalDecl()); if (It == InheritedFromBases.end()) return std::make_pair(nullptr, false); // This is an intermediary class. if (It->second) return std::make_pair( S.findInheritingConstructor(UseLoc, Ctor, It->second), It->second->constructsVirtualBase()); // This is the base class from which the constructor was inherited. return std::make_pair(Ctor, false); } }; /// Is the special member function which would be selected to perform the /// specified operation on the specified class type a constexpr constructor? static bool specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, Sema::CXXSpecialMember CSM, unsigned Quals, bool ConstRHS, CXXConstructorDecl *InheritedCtor = nullptr, Sema::InheritedConstructorInfo *Inherited = nullptr) { // If we're inheriting a constructor, see if we need to call it for this base // class. if (InheritedCtor) { assert(CSM == Sema::CXXDefaultConstructor); auto BaseCtor = Inherited->findConstructorForBase(ClassDecl, InheritedCtor).first; if (BaseCtor) return BaseCtor->isConstexpr(); } if (CSM == Sema::CXXDefaultConstructor) return ClassDecl->hasConstexprDefaultConstructor(); Sema::SpecialMemberOverloadResult SMOR = lookupCallFromSpecialMember(S, ClassDecl, CSM, Quals, ConstRHS); if (!SMOR.getMethod()) // A constructor we wouldn't select can't be "involved in initializing" // anything. return true; return SMOR.getMethod()->isConstexpr(); } /// Determine whether the specified special member function would be constexpr /// if it were implicitly defined. static bool defaultedSpecialMemberIsConstexpr( Sema &S, CXXRecordDecl *ClassDecl, Sema::CXXSpecialMember CSM, bool ConstArg, CXXConstructorDecl *InheritedCtor = nullptr, Sema::InheritedConstructorInfo *Inherited = nullptr) { if (!S.getLangOpts().CPlusPlus11) return false; // C++11 [dcl.constexpr]p4: // In the definition of a constexpr constructor [...] bool Ctor = true; switch (CSM) { case Sema::CXXDefaultConstructor: if (Inherited) break; // Since default constructor lookup is essentially trivial (and cannot // involve, for instance, template instantiation), we compute whether a // defaulted default constructor is constexpr directly within CXXRecordDecl. // // This is important for performance; we need to know whether the default // constructor is constexpr to determine whether the type is a literal type. return ClassDecl->defaultedDefaultConstructorIsConstexpr(); case Sema::CXXCopyConstructor: case Sema::CXXMoveConstructor: // For copy or move constructors, we need to perform overload resolution. break; case Sema::CXXCopyAssignment: case Sema::CXXMoveAssignment: if (!S.getLangOpts().CPlusPlus14) return false; // In C++1y, we need to perform overload resolution. Ctor = false; break; case Sema::CXXDestructor: case Sema::CXXInvalid: return false; } // -- if the class is a non-empty union, or for each non-empty anonymous // union member of a non-union class, exactly one non-static data member // shall be initialized; [DR1359] // // If we squint, this is guaranteed, since exactly one non-static data member // will be initialized (if the constructor isn't deleted), we just don't know // which one. if (Ctor && ClassDecl->isUnion()) return CSM == Sema::CXXDefaultConstructor ? ClassDecl->hasInClassInitializer() || !ClassDecl->hasVariantMembers() : true; // -- the class shall not have any virtual base classes; if (Ctor && ClassDecl->getNumVBases()) return false; // C++1y [class.copy]p26: // -- [the class] is a literal type, and if (!Ctor && !ClassDecl->isLiteral()) return false; // -- every constructor involved in initializing [...] base class // sub-objects shall be a constexpr constructor; // -- the assignment operator selected to copy/move each direct base // class is a constexpr function, and for (const auto &B : ClassDecl->bases()) { const RecordType *BaseType = B.getType()->getAs(); if (!BaseType) continue; CXXRecordDecl *BaseClassDecl = cast(BaseType->getDecl()); if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg, InheritedCtor, Inherited)) return false; } // -- every constructor involved in initializing non-static data members // [...] shall be a constexpr constructor; // -- every non-static data member and base class sub-object shall be // initialized // -- for each non-static data member of X that is of class type (or array // thereof), the assignment operator selected to copy/move that member is // a constexpr function for (const auto *F : ClassDecl->fields()) { if (F->isInvalidDecl()) continue; if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer()) continue; QualType BaseType = S.Context.getBaseElementType(F->getType()); if (const RecordType *RecordTy = BaseType->getAs()) { CXXRecordDecl *FieldRecDecl = cast(RecordTy->getDecl()); if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM, BaseType.getCVRQualifiers(), ConstArg && !F->isMutable())) return false; } else if (CSM == Sema::CXXDefaultConstructor) { return false; } } // All OK, it's constexpr! return true; } static Sema::ImplicitExceptionSpecification ComputeDefaultedSpecialMemberExceptionSpec( Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, Sema::InheritedConstructorInfo *ICI); static Sema::ImplicitExceptionSpecification computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, CXXMethodDecl *MD) { auto CSM = S.getSpecialMember(MD); if (CSM != Sema::CXXInvalid) return ComputeDefaultedSpecialMemberExceptionSpec(S, Loc, MD, CSM, nullptr); auto *CD = cast(MD); assert(CD->getInheritedConstructor() && "only special members have implicit exception specs"); Sema::InheritedConstructorInfo ICI( S, Loc, CD->getInheritedConstructor().getShadowDecl()); return ComputeDefaultedSpecialMemberExceptionSpec( S, Loc, CD, Sema::CXXDefaultConstructor, &ICI); } static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S, CXXMethodDecl *MD) { FunctionProtoType::ExtProtoInfo EPI; // Build an exception specification pointing back at this member. EPI.ExceptionSpec.Type = EST_Unevaluated; EPI.ExceptionSpec.SourceDecl = MD; // Set the calling convention to the default for C++ instance methods. EPI.ExtInfo = EPI.ExtInfo.withCallingConv( S.Context.getDefaultCallingConvention(/*IsVariadic=*/false, /*IsCXXMethod=*/true)); return EPI; } void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) { const FunctionProtoType *FPT = MD->getType()->castAs(); if (FPT->getExceptionSpecType() != EST_Unevaluated) return; // Evaluate the exception specification. auto IES = computeImplicitExceptionSpec(*this, Loc, MD); auto ESI = IES.getExceptionSpec(); // Update the type of the special member to use it. UpdateExceptionSpec(MD, ESI); // A user-provided destructor can be defined outside the class. When that // happens, be sure to update the exception specification on both // declarations. const FunctionProtoType *CanonicalFPT = MD->getCanonicalDecl()->getType()->castAs(); if (CanonicalFPT->getExceptionSpecType() == EST_Unevaluated) UpdateExceptionSpec(MD->getCanonicalDecl(), ESI); } void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { CXXRecordDecl *RD = MD->getParent(); CXXSpecialMember CSM = getSpecialMember(MD); assert(MD->isExplicitlyDefaulted() && CSM != CXXInvalid && "not an explicitly-defaulted special member"); // Whether this was the first-declared instance of the constructor. // This affects whether we implicitly add an exception spec and constexpr. bool First = MD == MD->getCanonicalDecl(); bool HadError = false; // C++11 [dcl.fct.def.default]p1: // A function that is explicitly defaulted shall // -- be a special member function (checked elsewhere), // -- have the same type (except for ref-qualifiers, and except that a // copy operation can take a non-const reference) as an implicit // declaration, and // -- not have default arguments. unsigned ExpectedParams = 1; if (CSM == CXXDefaultConstructor || CSM == CXXDestructor) ExpectedParams = 0; if (MD->getNumParams() != ExpectedParams) { // This also checks for default arguments: a copy or move constructor with a // default argument is classified as a default constructor, and assignment // operations and destructors can't have default arguments. Diag(MD->getLocation(), diag::err_defaulted_special_member_params) << CSM << MD->getSourceRange(); HadError = true; } else if (MD->isVariadic()) { Diag(MD->getLocation(), diag::err_defaulted_special_member_variadic) << CSM << MD->getSourceRange(); HadError = true; } const FunctionProtoType *Type = MD->getType()->getAs(); bool CanHaveConstParam = false; if (CSM == CXXCopyConstructor) CanHaveConstParam = RD->implicitCopyConstructorHasConstParam(); else if (CSM == CXXCopyAssignment) CanHaveConstParam = RD->implicitCopyAssignmentHasConstParam(); QualType ReturnType = Context.VoidTy; if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) { // Check for return type matching. ReturnType = Type->getReturnType(); QualType ExpectedReturnType = Context.getLValueReferenceType(Context.getTypeDeclType(RD)); if (!Context.hasSameType(ReturnType, ExpectedReturnType)) { Diag(MD->getLocation(), diag::err_defaulted_special_member_return_type) << (CSM == CXXMoveAssignment) << ExpectedReturnType; HadError = true; } // A defaulted special member cannot have cv-qualifiers. if (Type->getTypeQuals()) { Diag(MD->getLocation(), diag::err_defaulted_special_member_quals) << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus14; HadError = true; } } // Check for parameter type matching. QualType ArgType = ExpectedParams ? Type->getParamType(0) : QualType(); bool HasConstParam = false; if (ExpectedParams && ArgType->isReferenceType()) { // Argument must be reference to possibly-const T. QualType ReferentType = ArgType->getPointeeType(); HasConstParam = ReferentType.isConstQualified(); if (ReferentType.isVolatileQualified()) { Diag(MD->getLocation(), diag::err_defaulted_special_member_volatile_param) << CSM; HadError = true; } if (HasConstParam && !CanHaveConstParam) { if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment) { Diag(MD->getLocation(), diag::err_defaulted_special_member_copy_const_param) << (CSM == CXXCopyAssignment); // FIXME: Explain why this special member can't be const. } else { Diag(MD->getLocation(), diag::err_defaulted_special_member_move_const_param) << (CSM == CXXMoveAssignment); } HadError = true; } } else if (ExpectedParams) { // A copy assignment operator can take its argument by value, but a // defaulted one cannot. assert(CSM == CXXCopyAssignment && "unexpected non-ref argument"); Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref); HadError = true; } // C++11 [dcl.fct.def.default]p2: // An explicitly-defaulted function may be declared constexpr only if it // would have been implicitly declared as constexpr, // Do not apply this rule to members of class templates, since core issue 1358 // makes such functions always instantiate to constexpr functions. For // functions which cannot be constexpr (for non-constructors in C++11 and for // destructors in C++1y), this is checked elsewhere. bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, RD, CSM, HasConstParam); if ((getLangOpts().CPlusPlus14 ? !isa(MD) : isa(MD)) && MD->isConstexpr() && !Constexpr && MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { Diag(MD->getLocStart(), diag::err_incorrect_defaulted_constexpr) << CSM; // FIXME: Explain why the special member can't be constexpr. HadError = true; } // and may have an explicit exception-specification only if it is compatible // with the exception-specification on the implicit declaration. if (Type->hasExceptionSpec()) { // Delay the check if this is the first declaration of the special member, // since we may not have parsed some necessary in-class initializers yet. if (First) { // If the exception specification needs to be instantiated, do so now, // before we clobber it with an EST_Unevaluated specification below. if (Type->getExceptionSpecType() == EST_Uninstantiated) { InstantiateExceptionSpec(MD->getLocStart(), MD); Type = MD->getType()->getAs(); } DelayedDefaultedMemberExceptionSpecs.push_back(std::make_pair(MD, Type)); } else CheckExplicitlyDefaultedMemberExceptionSpec(MD, Type); } // If a function is explicitly defaulted on its first declaration, if (First) { // -- it is implicitly considered to be constexpr if the implicit // definition would be, MD->setConstexpr(Constexpr); // -- it is implicitly considered to have the same exception-specification // as if it had been implicitly declared, FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo(); EPI.ExceptionSpec.Type = EST_Unevaluated; EPI.ExceptionSpec.SourceDecl = MD; MD->setType(Context.getFunctionType(ReturnType, llvm::makeArrayRef(&ArgType, ExpectedParams), EPI)); } if (ShouldDeleteSpecialMember(MD, CSM)) { if (First) { SetDeclDeleted(MD, MD->getLocation()); } else { // C++11 [dcl.fct.def.default]p4: // [For a] user-provided explicitly-defaulted function [...] if such a // function is implicitly defined as deleted, the program is ill-formed. Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM; ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true); HadError = true; } } if (HadError) MD->setInvalidDecl(); } /// Check whether the exception specification provided for an /// explicitly-defaulted special member matches the exception specification /// that would have been generated for an implicit special member, per /// C++11 [dcl.fct.def.default]p2. void Sema::CheckExplicitlyDefaultedMemberExceptionSpec( CXXMethodDecl *MD, const FunctionProtoType *SpecifiedType) { // If the exception specification was explicitly specified but hadn't been // parsed when the method was defaulted, grab it now. if (SpecifiedType->getExceptionSpecType() == EST_Unparsed) SpecifiedType = MD->getTypeSourceInfo()->getType()->castAs(); // Compute the implicit exception specification. CallingConv CC = Context.getDefaultCallingConvention(/*IsVariadic=*/false, /*IsCXXMethod=*/true); FunctionProtoType::ExtProtoInfo EPI(CC); auto IES = computeImplicitExceptionSpec(*this, MD->getLocation(), MD); EPI.ExceptionSpec = IES.getExceptionSpec(); const FunctionProtoType *ImplicitType = cast( Context.getFunctionType(Context.VoidTy, None, EPI)); // Ensure that it matches. CheckEquivalentExceptionSpec( PDiag(diag::err_incorrect_defaulted_exception_spec) << getSpecialMember(MD), PDiag(), ImplicitType, SourceLocation(), SpecifiedType, MD->getLocation()); } void Sema::CheckDelayedMemberExceptionSpecs() { decltype(DelayedExceptionSpecChecks) Checks; decltype(DelayedDefaultedMemberExceptionSpecs) Specs; std::swap(Checks, DelayedExceptionSpecChecks); std::swap(Specs, DelayedDefaultedMemberExceptionSpecs); // Perform any deferred checking of exception specifications for virtual // destructors. for (auto &Check : Checks) CheckOverridingFunctionExceptionSpec(Check.first, Check.second); // Check that any explicitly-defaulted methods have exception specifications // compatible with their implicit exception specifications. for (auto &Spec : Specs) CheckExplicitlyDefaultedMemberExceptionSpec(Spec.first, Spec.second); } namespace { /// CRTP base class for visiting operations performed by a special member /// function (or inherited constructor). template struct SpecialMemberVisitor { Sema &S; CXXMethodDecl *MD; Sema::CXXSpecialMember CSM; Sema::InheritedConstructorInfo *ICI; // Properties of the special member, computed for convenience. bool IsConstructor = false, IsAssignment = false, ConstArg = false; SpecialMemberVisitor(Sema &S, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, Sema::InheritedConstructorInfo *ICI) : S(S), MD(MD), CSM(CSM), ICI(ICI) { switch (CSM) { case Sema::CXXDefaultConstructor: case Sema::CXXCopyConstructor: case Sema::CXXMoveConstructor: IsConstructor = true; break; case Sema::CXXCopyAssignment: case Sema::CXXMoveAssignment: IsAssignment = true; break; case Sema::CXXDestructor: break; case Sema::CXXInvalid: llvm_unreachable("invalid special member kind"); } if (MD->getNumParams()) { if (const ReferenceType *RT = MD->getParamDecl(0)->getType()->getAs()) ConstArg = RT->getPointeeType().isConstQualified(); } } Derived &getDerived() { return static_cast(*this); } /// Is this a "move" special member? bool isMove() const { return CSM == Sema::CXXMoveConstructor || CSM == Sema::CXXMoveAssignment; } /// Look up the corresponding special member in the given class. Sema::SpecialMemberOverloadResult lookupIn(CXXRecordDecl *Class, unsigned Quals, bool IsMutable) { return lookupCallFromSpecialMember(S, Class, CSM, Quals, ConstArg && !IsMutable); } /// Look up the constructor for the specified base class to see if it's /// overridden due to this being an inherited constructor. Sema::SpecialMemberOverloadResult lookupInheritedCtor(CXXRecordDecl *Class) { if (!ICI) return {}; assert(CSM == Sema::CXXDefaultConstructor); auto *BaseCtor = cast(MD)->getInheritedConstructor().getConstructor(); if (auto *MD = ICI->findConstructorForBase(Class, BaseCtor).first) return MD; return {}; } /// A base or member subobject. typedef llvm::PointerUnion Subobject; /// Get the location to use for a subobject in diagnostics. static SourceLocation getSubobjectLoc(Subobject Subobj) { // FIXME: For an indirect virtual base, the direct base leading to // the indirect virtual base would be a more useful choice. if (auto *B = Subobj.dyn_cast()) return B->getBaseTypeLoc(); else return Subobj.get()->getLocation(); } enum BasesToVisit { /// Visit all non-virtual (direct) bases. VisitNonVirtualBases, /// Visit all direct bases, virtual or not. VisitDirectBases, /// Visit all non-virtual bases, and all virtual bases if the class /// is not abstract. VisitPotentiallyConstructedBases, /// Visit all direct or virtual bases. VisitAllBases }; // Visit the bases and members of the class. bool visit(BasesToVisit Bases) { CXXRecordDecl *RD = MD->getParent(); if (Bases == VisitPotentiallyConstructedBases) Bases = RD->isAbstract() ? VisitNonVirtualBases : VisitAllBases; for (auto &B : RD->bases()) if ((Bases == VisitDirectBases || !B.isVirtual()) && getDerived().visitBase(&B)) return true; if (Bases == VisitAllBases) for (auto &B : RD->vbases()) if (getDerived().visitBase(&B)) return true; for (auto *F : RD->fields()) if (!F->isInvalidDecl() && !F->isUnnamedBitfield() && getDerived().visitField(F)) return true; return false; } }; } namespace { struct SpecialMemberDeletionInfo : SpecialMemberVisitor { bool Diagnose; SourceLocation Loc; bool AllFieldsAreConst; SpecialMemberDeletionInfo(Sema &S, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, Sema::InheritedConstructorInfo *ICI, bool Diagnose) : SpecialMemberVisitor(S, MD, CSM, ICI), Diagnose(Diagnose), Loc(MD->getLocation()), AllFieldsAreConst(true) {} bool inUnion() const { return MD->getParent()->isUnion(); } Sema::CXXSpecialMember getEffectiveCSM() { return ICI ? Sema::CXXInvalid : CSM; } bool visitBase(CXXBaseSpecifier *Base) { return shouldDeleteForBase(Base); } bool visitField(FieldDecl *Field) { return shouldDeleteForField(Field); } bool shouldDeleteForBase(CXXBaseSpecifier *Base); bool shouldDeleteForField(FieldDecl *FD); bool shouldDeleteForAllConstMembers(); bool shouldDeleteForClassSubobject(CXXRecordDecl *Class, Subobject Subobj, unsigned Quals); bool shouldDeleteForSubobjectCall(Subobject Subobj, Sema::SpecialMemberOverloadResult SMOR, bool IsDtorCallInCtor); bool isAccessible(Subobject Subobj, CXXMethodDecl *D); }; } /// Is the given special member inaccessible when used on the given /// sub-object. bool SpecialMemberDeletionInfo::isAccessible(Subobject Subobj, CXXMethodDecl *target) { /// If we're operating on a base class, the object type is the /// type of this special member. QualType objectTy; AccessSpecifier access = target->getAccess(); if (CXXBaseSpecifier *base = Subobj.dyn_cast()) { objectTy = S.Context.getTypeDeclType(MD->getParent()); access = CXXRecordDecl::MergeAccess(base->getAccessSpecifier(), access); // If we're operating on a field, the object type is the type of the field. } else { objectTy = S.Context.getTypeDeclType(target->getParent()); } return S.isSpecialMemberAccessibleForDeletion(target, access, objectTy); } /// Check whether we should delete a special member due to the implicit /// definition containing a call to a special member of a subobject. bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( Subobject Subobj, Sema::SpecialMemberOverloadResult SMOR, bool IsDtorCallInCtor) { CXXMethodDecl *Decl = SMOR.getMethod(); FieldDecl *Field = Subobj.dyn_cast(); int DiagKind = -1; if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) DiagKind = !Decl ? 0 : 1; else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous) DiagKind = 2; else if (!isAccessible(Subobj, Decl)) DiagKind = 3; else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() && !Decl->isTrivial()) { // A member of a union must have a trivial corresponding special member. // As a weird special case, a destructor call from a union's constructor // must be accessible and non-deleted, but need not be trivial. Such a // destructor is never actually called, but is semantically checked as // if it were. DiagKind = 4; } if (DiagKind == -1) return false; if (Diagnose) { if (Field) { S.Diag(Field->getLocation(), diag::note_deleted_special_member_class_subobject) << getEffectiveCSM() << MD->getParent() << /*IsField*/true << Field << DiagKind << IsDtorCallInCtor; } else { CXXBaseSpecifier *Base = Subobj.get(); S.Diag(Base->getLocStart(), diag::note_deleted_special_member_class_subobject) << getEffectiveCSM() << MD->getParent() << /*IsField*/false << Base->getType() << DiagKind << IsDtorCallInCtor; } if (DiagKind == 1) S.NoteDeletedFunction(Decl); // FIXME: Explain inaccessibility if DiagKind == 3. } return true; } /// Check whether we should delete a special member function due to having a /// direct or virtual base class or non-static data member of class type M. bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject( CXXRecordDecl *Class, Subobject Subobj, unsigned Quals) { FieldDecl *Field = Subobj.dyn_cast(); bool IsMutable = Field && Field->isMutable(); // C++11 [class.ctor]p5: // -- any direct or virtual base class, or non-static data member with no // brace-or-equal-initializer, has class type M (or array thereof) and // either M has no default constructor or overload resolution as applied // to M's default constructor results in an ambiguity or in a function // that is deleted or inaccessible // C++11 [class.copy]p11, C++11 [class.copy]p23: // -- a direct or virtual base class B that cannot be copied/moved because // overload resolution, as applied to B's corresponding special member, // results in an ambiguity or a function that is deleted or inaccessible // from the defaulted special member // C++11 [class.dtor]p5: // -- any direct or virtual base class [...] has a type with a destructor // that is deleted or inaccessible if (!(CSM == Sema::CXXDefaultConstructor && Field && Field->hasInClassInitializer()) && shouldDeleteForSubobjectCall(Subobj, lookupIn(Class, Quals, IsMutable), false)) return true; // C++11 [class.ctor]p5, C++11 [class.copy]p11: // -- any direct or virtual base class or non-static data member has a // type with a destructor that is deleted or inaccessible if (IsConstructor) { Sema::SpecialMemberOverloadResult SMOR = S.LookupSpecialMember(Class, Sema::CXXDestructor, false, false, false, false, false); if (shouldDeleteForSubobjectCall(Subobj, SMOR, true)) return true; } return false; } /// Check whether we should delete a special member function due to the class /// having a particular direct or virtual base class. bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) { CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl(); // If program is correct, BaseClass cannot be null, but if it is, the error // must be reported elsewhere. if (!BaseClass) return false; // If we have an inheriting constructor, check whether we're calling an // inherited constructor instead of a default constructor. Sema::SpecialMemberOverloadResult SMOR = lookupInheritedCtor(BaseClass); if (auto *BaseCtor = SMOR.getMethod()) { // Note that we do not check access along this path; other than that, // this is the same as shouldDeleteForSubobjectCall(Base, BaseCtor, false); // FIXME: Check that the base has a usable destructor! Sink this into // shouldDeleteForClassSubobject. if (BaseCtor->isDeleted() && Diagnose) { S.Diag(Base->getLocStart(), diag::note_deleted_special_member_class_subobject) << getEffectiveCSM() << MD->getParent() << /*IsField*/false << Base->getType() << /*Deleted*/1 << /*IsDtorCallInCtor*/false; S.NoteDeletedFunction(BaseCtor); } return BaseCtor->isDeleted(); } return shouldDeleteForClassSubobject(BaseClass, Base, 0); } /// Check whether we should delete a special member function due to the class /// having a particular non-static data member. bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { QualType FieldType = S.Context.getBaseElementType(FD->getType()); CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); if (CSM == Sema::CXXDefaultConstructor) { // For a default constructor, all references must be initialized in-class // and, if a union, it must have a non-const member. if (FieldType->isReferenceType() && !FD->hasInClassInitializer()) { if (Diagnose) S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field) << !!ICI << MD->getParent() << FD << FieldType << /*Reference*/0; return true; } // C++11 [class.ctor]p5: any non-variant non-static data member of // const-qualified type (or array thereof) with no // brace-or-equal-initializer does not have a user-provided default // constructor. if (!inUnion() && FieldType.isConstQualified() && !FD->hasInClassInitializer() && (!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor())) { if (Diagnose) S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field) << !!ICI << MD->getParent() << FD << FD->getType() << /*Const*/1; return true; } if (inUnion() && !FieldType.isConstQualified()) AllFieldsAreConst = false; } else if (CSM == Sema::CXXCopyConstructor) { // For a copy constructor, data members must not be of rvalue reference // type. if (FieldType->isRValueReferenceType()) { if (Diagnose) S.Diag(FD->getLocation(), diag::note_deleted_copy_ctor_rvalue_reference) << MD->getParent() << FD << FieldType; return true; } } else if (IsAssignment) { // For an assignment operator, data members must not be of reference type. if (FieldType->isReferenceType()) { if (Diagnose) S.Diag(FD->getLocation(), diag::note_deleted_assign_field) << isMove() << MD->getParent() << FD << FieldType << /*Reference*/0; return true; } if (!FieldRecord && FieldType.isConstQualified()) { // C++11 [class.copy]p23: // -- a non-static data member of const non-class type (or array thereof) if (Diagnose) S.Diag(FD->getLocation(), diag::note_deleted_assign_field) << isMove() << MD->getParent() << FD << FD->getType() << /*Const*/1; return true; } } if (FieldRecord) { // Some additional restrictions exist on the variant members. if (!inUnion() && FieldRecord->isUnion() && FieldRecord->isAnonymousStructOrUnion()) { bool AllVariantFieldsAreConst = true; // FIXME: Handle anonymous unions declared within anonymous unions. for (auto *UI : FieldRecord->fields()) { QualType UnionFieldType = S.Context.getBaseElementType(UI->getType()); if (!UnionFieldType.isConstQualified()) AllVariantFieldsAreConst = false; CXXRecordDecl *UnionFieldRecord = UnionFieldType->getAsCXXRecordDecl(); if (UnionFieldRecord && shouldDeleteForClassSubobject(UnionFieldRecord, UI, UnionFieldType.getCVRQualifiers())) return true; } // At least one member in each anonymous union must be non-const if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst && !FieldRecord->field_empty()) { if (Diagnose) S.Diag(FieldRecord->getLocation(), diag::note_deleted_default_ctor_all_const) << !!ICI << MD->getParent() << /*anonymous union*/1; return true; } // Don't check the implicit member of the anonymous union type. // This is technically non-conformant, but sanity demands it. return false; } if (shouldDeleteForClassSubobject(FieldRecord, FD, FieldType.getCVRQualifiers())) return true; } return false; } /// C++11 [class.ctor] p5: /// A defaulted default constructor for a class X is defined as deleted if /// X is a union and all of its variant members are of const-qualified type. bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() { // This is a silly definition, because it gives an empty union a deleted // default constructor. Don't do that. if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst) { bool AnyFields = false; for (auto *F : MD->getParent()->fields()) if ((AnyFields = !F->isUnnamedBitfield())) break; if (!AnyFields) return false; if (Diagnose) S.Diag(MD->getParent()->getLocation(), diag::note_deleted_default_ctor_all_const) << !!ICI << MD->getParent() << /*not anonymous union*/0; return true; } return false; } /// Determine whether a defaulted special member function should be defined as /// deleted, as specified in C++11 [class.ctor]p5, C++11 [class.copy]p11, /// C++11 [class.copy]p23, and C++11 [class.dtor]p5. bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, InheritedConstructorInfo *ICI, bool Diagnose) { if (MD->isInvalidDecl()) return false; CXXRecordDecl *RD = MD->getParent(); assert(!RD->isDependentType() && "do deletion after instantiation"); if (!LangOpts.CPlusPlus11 || RD->isInvalidDecl()) return false; // C++11 [expr.lambda.prim]p19: // The closure type associated with a lambda-expression has a // deleted (8.4.3) default constructor and a deleted copy // assignment operator. if (RD->isLambda() && (CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment)) { if (Diagnose) Diag(RD->getLocation(), diag::note_lambda_decl); return true; } // For an anonymous struct or union, the copy and assignment special members // will never be used, so skip the check. For an anonymous union declared at // namespace scope, the constructor and destructor are used. if (CSM != CXXDefaultConstructor && CSM != CXXDestructor && RD->isAnonymousStructOrUnion()) return false; // C++11 [class.copy]p7, p18: // If the class definition declares a move constructor or move assignment // operator, an implicitly declared copy constructor or copy assignment // operator is defined as deleted. if (MD->isImplicit() && (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) { CXXMethodDecl *UserDeclaredMove = nullptr; // In Microsoft mode up to MSVC 2013, a user-declared move only causes the // deletion of the corresponding copy operation, not both copy operations. // MSVC 2015 has adopted the standards conforming behavior. bool DeletesOnlyMatchingCopy = getLangOpts().MSVCCompat && !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015); if (RD->hasUserDeclaredMoveConstructor() && (!DeletesOnlyMatchingCopy || CSM == CXXCopyConstructor)) { if (!Diagnose) return true; // Find any user-declared move constructor. for (auto *I : RD->ctors()) { if (I->isMoveConstructor()) { UserDeclaredMove = I; break; } } assert(UserDeclaredMove); } else if (RD->hasUserDeclaredMoveAssignment() && (!DeletesOnlyMatchingCopy || CSM == CXXCopyAssignment)) { if (!Diagnose) return true; // Find any user-declared move assignment operator. for (auto *I : RD->methods()) { if (I->isMoveAssignmentOperator()) { UserDeclaredMove = I; break; } } assert(UserDeclaredMove); } if (UserDeclaredMove) { Diag(UserDeclaredMove->getLocation(), diag::note_deleted_copy_user_declared_move) << (CSM == CXXCopyAssignment) << RD << UserDeclaredMove->isMoveAssignmentOperator(); return true; } } // Do access control from the special member function ContextRAII MethodContext(*this, MD); // C++11 [class.dtor]p5: // -- for a virtual destructor, lookup of the non-array deallocation function // results in an ambiguity or in a function that is deleted or inaccessible if (CSM == CXXDestructor && MD->isVirtual()) { FunctionDecl *OperatorDelete = nullptr; DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Delete); if (FindDeallocationFunction(MD->getLocation(), MD->getParent(), Name, OperatorDelete, /*Diagnose*/false)) { if (Diagnose) Diag(RD->getLocation(), diag::note_deleted_dtor_no_operator_delete); return true; } } SpecialMemberDeletionInfo SMI(*this, MD, CSM, ICI, Diagnose); // Per DR1611, do not consider virtual bases of constructors of abstract // classes, since we are not going to construct them. // Per DR1658, do not consider virtual bases of destructors of abstract // classes either. // Per DR2180, for assignment operators we only assign (and thus only // consider) direct bases. if (SMI.visit(SMI.IsAssignment ? SMI.VisitDirectBases : SMI.VisitPotentiallyConstructedBases)) return true; if (SMI.shouldDeleteForAllConstMembers()) return true; if (getLangOpts().CUDA) { // We should delete the special member in CUDA mode if target inference // failed. return inferCUDATargetForImplicitSpecialMember(RD, CSM, MD, SMI.ConstArg, Diagnose); } return false; } /// Perform lookup for a special member of the specified kind, and determine /// whether it is trivial. If the triviality can be determined without the /// lookup, skip it. This is intended for use when determining whether a /// special member of a containing object is trivial, and thus does not ever /// perform overload resolution for default constructors. /// /// If \p Selected is not \c NULL, \c *Selected will be filled in with the /// member that was most likely to be intended to be trivial, if any. static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM, unsigned Quals, bool ConstRHS, CXXMethodDecl **Selected) { if (Selected) *Selected = nullptr; switch (CSM) { case Sema::CXXInvalid: llvm_unreachable("not a special member"); case Sema::CXXDefaultConstructor: // C++11 [class.ctor]p5: // A default constructor is trivial if: // - all the [direct subobjects] have trivial default constructors // // Note, no overload resolution is performed in this case. if (RD->hasTrivialDefaultConstructor()) return true; if (Selected) { // If there's a default constructor which could have been trivial, dig it // out. Otherwise, if there's any user-provided default constructor, point // to that as an example of why there's not a trivial one. CXXConstructorDecl *DefCtor = nullptr; if (RD->needsImplicitDefaultConstructor()) S.DeclareImplicitDefaultConstructor(RD); for (auto *CI : RD->ctors()) { if (!CI->isDefaultConstructor()) continue; DefCtor = CI; if (!DefCtor->isUserProvided()) break; } *Selected = DefCtor; } return false; case Sema::CXXDestructor: // C++11 [class.dtor]p5: // A destructor is trivial if: // - all the direct [subobjects] have trivial destructors if (RD->hasTrivialDestructor()) return true; if (Selected) { if (RD->needsImplicitDestructor()) S.DeclareImplicitDestructor(RD); *Selected = RD->getDestructor(); } return false; case Sema::CXXCopyConstructor: // C++11 [class.copy]p12: // A copy constructor is trivial if: // - the constructor selected to copy each direct [subobject] is trivial if (RD->hasTrivialCopyConstructor()) { if (Quals == Qualifiers::Const) // We must either select the trivial copy constructor or reach an // ambiguity; no need to actually perform overload resolution. return true; } else if (!Selected) { return false; } // In C++98, we are not supposed to perform overload resolution here, but we // treat that as a language defect, as suggested on cxx-abi-dev, to treat // cases like B as having a non-trivial copy constructor: // struct A { template A(T&); }; // struct B { mutable A a; }; goto NeedOverloadResolution; case Sema::CXXCopyAssignment: // C++11 [class.copy]p25: // A copy assignment operator is trivial if: // - the assignment operator selected to copy each direct [subobject] is // trivial if (RD->hasTrivialCopyAssignment()) { if (Quals == Qualifiers::Const) return true; } else if (!Selected) { return false; } // In C++98, we are not supposed to perform overload resolution here, but we // treat that as a language defect. goto NeedOverloadResolution; case Sema::CXXMoveConstructor: case Sema::CXXMoveAssignment: NeedOverloadResolution: Sema::SpecialMemberOverloadResult SMOR = lookupCallFromSpecialMember(S, RD, CSM, Quals, ConstRHS); // The standard doesn't describe how to behave if the lookup is ambiguous. // We treat it as not making the member non-trivial, just like the standard // mandates for the default constructor. This should rarely matter, because // the member will also be deleted. if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous) return true; if (!SMOR.getMethod()) { assert(SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted); return false; } // We deliberately don't check if we found a deleted special member. We're // not supposed to! if (Selected) *Selected = SMOR.getMethod(); return SMOR.getMethod()->isTrivial(); } llvm_unreachable("unknown special method kind"); } static CXXConstructorDecl *findUserDeclaredCtor(CXXRecordDecl *RD) { for (auto *CI : RD->ctors()) if (!CI->isImplicit()) return CI; // Look for constructor templates. typedef CXXRecordDecl::specific_decl_iterator tmpl_iter; for (tmpl_iter TI(RD->decls_begin()), TE(RD->decls_end()); TI != TE; ++TI) { if (CXXConstructorDecl *CD = dyn_cast(TI->getTemplatedDecl())) return CD; } return nullptr; } /// The kind of subobject we are checking for triviality. The values of this /// enumeration are used in diagnostics. enum TrivialSubobjectKind { /// The subobject is a base class. TSK_BaseClass, /// The subobject is a non-static data member. TSK_Field, /// The object is actually the complete object. TSK_CompleteObject }; /// Check whether the special member selected for a given type would be trivial. static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc, QualType SubType, bool ConstRHS, Sema::CXXSpecialMember CSM, TrivialSubobjectKind Kind, bool Diagnose) { CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl(); if (!SubRD) return true; CXXMethodDecl *Selected; if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(), ConstRHS, Diagnose ? &Selected : nullptr)) return true; if (Diagnose) { if (ConstRHS) SubType.addConst(); if (!Selected && CSM == Sema::CXXDefaultConstructor) { S.Diag(SubobjLoc, diag::note_nontrivial_no_def_ctor) << Kind << SubType.getUnqualifiedType(); if (CXXConstructorDecl *CD = findUserDeclaredCtor(SubRD)) S.Diag(CD->getLocation(), diag::note_user_declared_ctor); } else if (!Selected) S.Diag(SubobjLoc, diag::note_nontrivial_no_copy) << Kind << SubType.getUnqualifiedType() << CSM << SubType; else if (Selected->isUserProvided()) { if (Kind == TSK_CompleteObject) S.Diag(Selected->getLocation(), diag::note_nontrivial_user_provided) << Kind << SubType.getUnqualifiedType() << CSM; else { S.Diag(SubobjLoc, diag::note_nontrivial_user_provided) << Kind << SubType.getUnqualifiedType() << CSM; S.Diag(Selected->getLocation(), diag::note_declared_at); } } else { if (Kind != TSK_CompleteObject) S.Diag(SubobjLoc, diag::note_nontrivial_subobject) << Kind << SubType.getUnqualifiedType() << CSM; // Explain why the defaulted or deleted special member isn't trivial. S.SpecialMemberIsTrivial(Selected, CSM, Diagnose); } } return false; } /// Check whether the members of a class type allow a special member to be /// trivial. static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM, bool ConstArg, bool Diagnose) { for (const auto *FI : RD->fields()) { if (FI->isInvalidDecl() || FI->isUnnamedBitfield()) continue; QualType FieldType = S.Context.getBaseElementType(FI->getType()); // Pretend anonymous struct or union members are members of this class. if (FI->isAnonymousStructOrUnion()) { if (!checkTrivialClassMembers(S, FieldType->getAsCXXRecordDecl(), CSM, ConstArg, Diagnose)) return false; continue; } // C++11 [class.ctor]p5: // A default constructor is trivial if [...] // -- no non-static data member of its class has a // brace-or-equal-initializer if (CSM == Sema::CXXDefaultConstructor && FI->hasInClassInitializer()) { if (Diagnose) S.Diag(FI->getLocation(), diag::note_nontrivial_in_class_init) << FI; return false; } // Objective C ARC 4.3.5: // [...] nontrivally ownership-qualified types are [...] not trivially // default constructible, copy constructible, move constructible, copy // assignable, move assignable, or destructible [...] if (FieldType.hasNonTrivialObjCLifetime()) { if (Diagnose) S.Diag(FI->getLocation(), diag::note_nontrivial_objc_ownership) << RD << FieldType.getObjCLifetime(); return false; } bool ConstRHS = ConstArg && !FI->isMutable(); if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, ConstRHS, CSM, TSK_Field, Diagnose)) return false; } return true; } /// Diagnose why the specified class does not have a trivial special member of /// the given kind. void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) { QualType Ty = Context.getRecordType(RD); bool ConstArg = (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment); checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, ConstArg, CSM, TSK_CompleteObject, /*Diagnose*/true); } /// Determine whether a defaulted or deleted special member function is trivial, /// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12, /// C++11 [class.copy]p25, and C++11 [class.dtor]p5. bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, bool Diagnose) { assert(!MD->isUserProvided() && CSM != CXXInvalid && "not special enough"); CXXRecordDecl *RD = MD->getParent(); bool ConstArg = false; // C++11 [class.copy]p12, p25: [DR1593] // A [special member] is trivial if [...] its parameter-type-list is // equivalent to the parameter-type-list of an implicit declaration [...] switch (CSM) { case CXXDefaultConstructor: case CXXDestructor: // Trivial default constructors and destructors cannot have parameters. break; case CXXCopyConstructor: case CXXCopyAssignment: { // Trivial copy operations always have const, non-volatile parameter types. ConstArg = true; const ParmVarDecl *Param0 = MD->getParamDecl(0); const ReferenceType *RT = Param0->getType()->getAs(); if (!RT || RT->getPointeeType().getCVRQualifiers() != Qualifiers::Const) { if (Diagnose) Diag(Param0->getLocation(), diag::note_nontrivial_param_type) << Param0->getSourceRange() << Param0->getType() << Context.getLValueReferenceType( Context.getRecordType(RD).withConst()); return false; } break; } case CXXMoveConstructor: case CXXMoveAssignment: { // Trivial move operations always have non-cv-qualified parameters. const ParmVarDecl *Param0 = MD->getParamDecl(0); const RValueReferenceType *RT = Param0->getType()->getAs(); if (!RT || RT->getPointeeType().getCVRQualifiers()) { if (Diagnose) Diag(Param0->getLocation(), diag::note_nontrivial_param_type) << Param0->getSourceRange() << Param0->getType() << Context.getRValueReferenceType(Context.getRecordType(RD)); return false; } break; } case CXXInvalid: llvm_unreachable("not a special member"); } if (MD->getMinRequiredArguments() < MD->getNumParams()) { if (Diagnose) Diag(MD->getParamDecl(MD->getMinRequiredArguments())->getLocation(), diag::note_nontrivial_default_arg) << MD->getParamDecl(MD->getMinRequiredArguments())->getSourceRange(); return false; } if (MD->isVariadic()) { if (Diagnose) Diag(MD->getLocation(), diag::note_nontrivial_variadic); return false; } // C++11 [class.ctor]p5, C++11 [class.dtor]p5: // A copy/move [constructor or assignment operator] is trivial if // -- the [member] selected to copy/move each direct base class subobject // is trivial // // C++11 [class.copy]p12, C++11 [class.copy]p25: // A [default constructor or destructor] is trivial if // -- all the direct base classes have trivial [default constructors or // destructors] for (const auto &BI : RD->bases()) if (!checkTrivialSubobjectCall(*this, BI.getLocStart(), BI.getType(), ConstArg, CSM, TSK_BaseClass, Diagnose)) return false; // C++11 [class.ctor]p5, C++11 [class.dtor]p5: // A copy/move [constructor or assignment operator] for a class X is // trivial if // -- for each non-static data member of X that is of class type (or array // thereof), the constructor selected to copy/move that member is // trivial // // C++11 [class.copy]p12, C++11 [class.copy]p25: // A [default constructor or destructor] is trivial if // -- for all of the non-static data members of its class that are of class // type (or array thereof), each such class has a trivial [default // constructor or destructor] if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, Diagnose)) return false; // C++11 [class.dtor]p5: // A destructor is trivial if [...] // -- the destructor is not virtual if (CSM == CXXDestructor && MD->isVirtual()) { if (Diagnose) Diag(MD->getLocation(), diag::note_nontrivial_virtual_dtor) << RD; return false; } // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25: // A [special member] for class X is trivial if [...] // -- class X has no virtual functions and no virtual base classes if (CSM != CXXDestructor && MD->getParent()->isDynamicClass()) { if (!Diagnose) return false; if (RD->getNumVBases()) { // Check for virtual bases. We already know that the corresponding // member in all bases is trivial, so vbases must all be direct. CXXBaseSpecifier &BS = *RD->vbases_begin(); assert(BS.isVirtual()); Diag(BS.getLocStart(), diag::note_nontrivial_has_virtual) << RD << 1; return false; } // Must have a virtual method. for (const auto *MI : RD->methods()) { if (MI->isVirtual()) { SourceLocation MLoc = MI->getLocStart(); Diag(MLoc, diag::note_nontrivial_has_virtual) << RD << 0; return false; } } llvm_unreachable("dynamic class with no vbases and no virtual functions"); } // Looks like it's trivial! return true; } namespace { struct FindHiddenVirtualMethod { Sema *S; CXXMethodDecl *Method; llvm::SmallPtrSet OverridenAndUsingBaseMethods; SmallVector OverloadedMethods; private: /// Check whether any most overriden method from MD in Methods static bool CheckMostOverridenMethods( const CXXMethodDecl *MD, const llvm::SmallPtrSetImpl &Methods) { if (MD->size_overridden_methods() == 0) return Methods.count(MD->getCanonicalDecl()); for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), E = MD->end_overridden_methods(); I != E; ++I) if (CheckMostOverridenMethods(*I, Methods)) return true; return false; } public: /// Member lookup function that determines whether a given C++ /// method overloads virtual methods in a base class without overriding any, /// to be used with CXXRecordDecl::lookupInBases(). bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { RecordDecl *BaseRecord = Specifier->getType()->getAs()->getDecl(); DeclarationName Name = Method->getDeclName(); assert(Name.getNameKind() == DeclarationName::Identifier); bool foundSameNameMethod = false; SmallVector overloadedMethods; for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); Path.Decls = Path.Decls.slice(1)) { NamedDecl *D = Path.Decls.front(); if (CXXMethodDecl *MD = dyn_cast(D)) { MD = MD->getCanonicalDecl(); foundSameNameMethod = true; // Interested only in hidden virtual methods. if (!MD->isVirtual()) continue; // If the method we are checking overrides a method from its base // don't warn about the other overloaded methods. Clang deviates from // GCC by only diagnosing overloads of inherited virtual functions that // do not override any other virtual functions in the base. GCC's // -Woverloaded-virtual diagnoses any derived function hiding a virtual // function from a base class. These cases may be better served by a // warning (not specific to virtual functions) on call sites when the // call would select a different function from the base class, were it // visible. // See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example. if (!S->IsOverload(Method, MD, false)) return true; // Collect the overload only if its hidden. if (!CheckMostOverridenMethods(MD, OverridenAndUsingBaseMethods)) overloadedMethods.push_back(MD); } } if (foundSameNameMethod) OverloadedMethods.append(overloadedMethods.begin(), overloadedMethods.end()); return foundSameNameMethod; } }; } // end anonymous namespace /// \brief Add the most overriden methods from MD to Methods static void AddMostOverridenMethods(const CXXMethodDecl *MD, llvm::SmallPtrSetImpl& Methods) { if (MD->size_overridden_methods() == 0) Methods.insert(MD->getCanonicalDecl()); for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), E = MD->end_overridden_methods(); I != E; ++I) AddMostOverridenMethods(*I, Methods); } /// \brief Check if a method overloads virtual methods in a base class without /// overriding any. void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD, SmallVectorImpl &OverloadedMethods) { if (!MD->getDeclName().isIdentifier()) return; CXXBasePaths Paths(/*FindAmbiguities=*/true, // true to look in all bases. /*bool RecordPaths=*/false, /*bool DetectVirtual=*/false); FindHiddenVirtualMethod FHVM; FHVM.Method = MD; FHVM.S = this; // Keep the base methods that were overriden or introduced in the subclass // by 'using' in a set. A base method not in this set is hidden. CXXRecordDecl *DC = MD->getParent(); DeclContext::lookup_result R = DC->lookup(MD->getDeclName()); for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { NamedDecl *ND = *I; if (UsingShadowDecl *shad = dyn_cast(*I)) ND = shad->getTargetDecl(); if (CXXMethodDecl *MD = dyn_cast(ND)) AddMostOverridenMethods(MD, FHVM.OverridenAndUsingBaseMethods); } if (DC->lookupInBases(FHVM, Paths)) OverloadedMethods = FHVM.OverloadedMethods; } void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD, SmallVectorImpl &OverloadedMethods) { for (unsigned i = 0, e = OverloadedMethods.size(); i != e; ++i) { CXXMethodDecl *overloadedMD = OverloadedMethods[i]; PartialDiagnostic PD = PDiag( diag::note_hidden_overloaded_virtual_declared_here) << overloadedMD; HandleFunctionTypeMismatch(PD, MD->getType(), overloadedMD->getType()); Diag(overloadedMD->getLocation(), PD); } } /// \brief Diagnose methods which overload virtual methods in a base class /// without overriding any. void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) { if (MD->isInvalidDecl()) return; if (Diags.isIgnored(diag::warn_overloaded_virtual, MD->getLocation())) return; SmallVector OverloadedMethods; FindHiddenVirtualMethods(MD, OverloadedMethods); if (!OverloadedMethods.empty()) { Diag(MD->getLocation(), diag::warn_overloaded_virtual) << MD << (OverloadedMethods.size() > 1); NoteHiddenVirtualMethods(MD, OverloadedMethods); } } void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac, SourceLocation RBrac, AttributeList *AttrList) { if (!TagDecl) return; AdjustDeclIfTemplate(TagDecl); for (const AttributeList* l = AttrList; l; l = l->getNext()) { if (l->getKind() != AttributeList::AT_Visibility) continue; l->setInvalid(); Diag(l->getLoc(), diag::warn_attribute_after_definition_ignored) << l->getName(); } ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef( // strict aliasing violation! reinterpret_cast(FieldCollector->getCurFields()), FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList); CheckCompletedCXXClass(dyn_cast_or_null(TagDecl)); } /// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared /// special functions, such as the default constructor, copy /// constructor, or destructor, to the given C++ class (C++ /// [special]p1). This routine can only be executed just before the /// definition of the class is complete. void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { if (ClassDecl->needsImplicitDefaultConstructor()) { ++ASTContext::NumImplicitDefaultConstructors; if (ClassDecl->hasInheritedConstructor()) DeclareImplicitDefaultConstructor(ClassDecl); } if (ClassDecl->needsImplicitCopyConstructor()) { ++ASTContext::NumImplicitCopyConstructors; // If the properties or semantics of the copy constructor couldn't be // determined while the class was being declared, force a declaration // of it now. if (ClassDecl->needsOverloadResolutionForCopyConstructor() || ClassDecl->hasInheritedConstructor()) DeclareImplicitCopyConstructor(ClassDecl); // For the MS ABI we need to know whether the copy ctor is deleted. A // prerequisite for deleting the implicit copy ctor is that the class has a // move ctor or move assignment that is either user-declared or whose // semantics are inherited from a subobject. FIXME: We should provide a more // direct way for CodeGen to ask whether the constructor was deleted. else if (Context.getTargetInfo().getCXXABI().isMicrosoft() && (ClassDecl->hasUserDeclaredMoveConstructor() || ClassDecl->needsOverloadResolutionForMoveConstructor() || ClassDecl->hasUserDeclaredMoveAssignment() || ClassDecl->needsOverloadResolutionForMoveAssignment())) DeclareImplicitCopyConstructor(ClassDecl); } if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) { ++ASTContext::NumImplicitMoveConstructors; if (ClassDecl->needsOverloadResolutionForMoveConstructor() || ClassDecl->hasInheritedConstructor()) DeclareImplicitMoveConstructor(ClassDecl); } if (ClassDecl->needsImplicitCopyAssignment()) { ++ASTContext::NumImplicitCopyAssignmentOperators; // If we have a dynamic class, then the copy assignment operator may be // virtual, so we have to declare it immediately. This ensures that, e.g., // it shows up in the right place in the vtable and that we diagnose // problems with the implicit exception specification. if (ClassDecl->isDynamicClass() || ClassDecl->needsOverloadResolutionForCopyAssignment() || ClassDecl->hasInheritedAssignment()) DeclareImplicitCopyAssignment(ClassDecl); } if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveAssignment()) { ++ASTContext::NumImplicitMoveAssignmentOperators; // Likewise for the move assignment operator. if (ClassDecl->isDynamicClass() || ClassDecl->needsOverloadResolutionForMoveAssignment() || ClassDecl->hasInheritedAssignment()) DeclareImplicitMoveAssignment(ClassDecl); } if (ClassDecl->needsImplicitDestructor()) { ++ASTContext::NumImplicitDestructors; // If we have a dynamic class, then the destructor may be virtual, so we // have to declare the destructor immediately. This ensures that, e.g., it // shows up in the right place in the vtable and that we diagnose problems // with the implicit exception specification. if (ClassDecl->isDynamicClass() || ClassDecl->needsOverloadResolutionForDestructor()) DeclareImplicitDestructor(ClassDecl); } } unsigned Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) { if (!D) return 0; // The order of template parameters is not important here. All names // get added to the same scope. SmallVector ParameterLists; if (TemplateDecl *TD = dyn_cast(D)) D = TD->getTemplatedDecl(); if (auto *PSD = dyn_cast(D)) ParameterLists.push_back(PSD->getTemplateParameters()); if (DeclaratorDecl *DD = dyn_cast(D)) { for (unsigned i = 0; i < DD->getNumTemplateParameterLists(); ++i) ParameterLists.push_back(DD->getTemplateParameterList(i)); if (FunctionDecl *FD = dyn_cast(D)) { if (FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate()) ParameterLists.push_back(FTD->getTemplateParameters()); } } if (TagDecl *TD = dyn_cast(D)) { for (unsigned i = 0; i < TD->getNumTemplateParameterLists(); ++i) ParameterLists.push_back(TD->getTemplateParameterList(i)); if (CXXRecordDecl *RD = dyn_cast(TD)) { if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate()) ParameterLists.push_back(CTD->getTemplateParameters()); } } unsigned Count = 0; for (TemplateParameterList *Params : ParameterLists) { if (Params->size() > 0) // Ignore explicit specializations; they don't contribute to the template // depth. ++Count; for (NamedDecl *Param : *Params) { if (Param->getDeclName()) { S->AddDecl(Param); IdResolver.AddDecl(Param); } } } return Count; } void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) { if (!RecordD) return; AdjustDeclIfTemplate(RecordD); CXXRecordDecl *Record = cast(RecordD); PushDeclContext(S, Record); } void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *RecordD) { if (!RecordD) return; PopDeclContext(); } /// This is used to implement the constant expression evaluation part of the /// attribute enable_if extension. There is nothing in standard C++ which would /// require reentering parameters. void Sema::ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param) { if (!Param) return; S->AddDecl(Param); if (Param->getDeclName()) IdResolver.AddDecl(Param); } /// ActOnStartDelayedCXXMethodDeclaration - We have completed /// parsing a top-level (non-nested) C++ class, and we are now /// parsing those parts of the given Method declaration that could /// not be parsed earlier (C++ [class.mem]p2), such as default /// arguments. This action should enter the scope of the given /// Method declaration as if we had just parsed the qualified method /// name. However, it should not bring the parameters into scope; /// that will be performed by ActOnDelayedCXXMethodParameter. void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { } /// ActOnDelayedCXXMethodParameter - We've already started a delayed /// C++ method declaration. We're (re-)introducing the given /// function parameter into scope for use in parsing later parts of /// the method declaration. For example, we could see an /// ActOnParamDefaultArgument event for this parameter. void Sema::ActOnDelayedCXXMethodParameter(Scope *S, Decl *ParamD) { if (!ParamD) return; ParmVarDecl *Param = cast(ParamD); // If this parameter has an unparsed default argument, clear it out // to make way for the parsed default argument. if (Param->hasUnparsedDefaultArg()) Param->setDefaultArg(nullptr); S->AddDecl(Param); if (Param->getDeclName()) IdResolver.AddDecl(Param); } /// ActOnFinishDelayedCXXMethodDeclaration - We have finished /// processing the delayed method declaration for Method. The method /// declaration is now considered finished. There may be a separate /// ActOnStartOfFunctionDef action later (not necessarily /// immediately!) for this method, if it was also defined inside the /// class body. void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { if (!MethodD) return; AdjustDeclIfTemplate(MethodD); FunctionDecl *Method = cast(MethodD); // Now that we have our default arguments, check the constructor // again. It could produce additional diagnostics or affect whether // the class has implicitly-declared destructors, among other // things. if (CXXConstructorDecl *Constructor = dyn_cast(Method)) CheckConstructor(Constructor); // Check the default arguments, which we may have added. if (!Method->isInvalidDecl()) CheckCXXDefaultArguments(Method); } /// CheckConstructorDeclarator - Called by ActOnDeclarator to check /// the well-formedness of the constructor declarator @p D with type @p /// R. If there are any errors in the declarator, this routine will /// emit diagnostics and set the invalid bit to true. In any case, the type /// will be updated to reflect a well-formed type for the constructor and /// returned. QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, StorageClass &SC) { bool isVirtual = D.getDeclSpec().isVirtualSpecified(); // C++ [class.ctor]p3: // A constructor shall not be virtual (10.3) or static (9.4). A // constructor can be invoked for a const, volatile or const // volatile object. A constructor shall not be declared const, // volatile, or const volatile (9.3.2). if (isVirtual) { if (!D.isInvalidType()) Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be) << "virtual" << SourceRange(D.getDeclSpec().getVirtualSpecLoc()) << SourceRange(D.getIdentifierLoc()); D.setInvalidType(); } if (SC == SC_Static) { if (!D.isInvalidType()) Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be) << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) << SourceRange(D.getIdentifierLoc()); D.setInvalidType(); SC = SC_None; } if (unsigned TypeQuals = D.getDeclSpec().getTypeQualifiers()) { diagnoseIgnoredQualifiers( diag::err_constructor_return_type, TypeQuals, SourceLocation(), D.getDeclSpec().getConstSpecLoc(), D.getDeclSpec().getVolatileSpecLoc(), D.getDeclSpec().getRestrictSpecLoc(), D.getDeclSpec().getAtomicSpecLoc()); D.setInvalidType(); } DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.TypeQuals != 0) { if (FTI.TypeQuals & Qualifiers::Const) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) << "const" << SourceRange(D.getIdentifierLoc()); if (FTI.TypeQuals & Qualifiers::Volatile) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) << "volatile" << SourceRange(D.getIdentifierLoc()); if (FTI.TypeQuals & Qualifiers::Restrict) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) << "restrict" << SourceRange(D.getIdentifierLoc()); D.setInvalidType(); } // C++0x [class.ctor]p4: // A constructor shall not be declared with a ref-qualifier. if (FTI.hasRefQualifier()) { Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor) << FTI.RefQualifierIsLValueRef << FixItHint::CreateRemoval(FTI.getRefQualifierLoc()); D.setInvalidType(); } // Rebuild the function type "R" without any type qualifiers (in // case any of the errors above fired) and with "void" as the // return type, since constructors don't have return types. const FunctionProtoType *Proto = R->getAs(); if (Proto->getReturnType() == Context.VoidTy && !D.isInvalidType()) return R; FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); EPI.TypeQuals = 0; EPI.RefQualifier = RQ_None; return Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI); } /// CheckConstructor - Checks a fully-formed constructor for /// well-formedness, issuing any diagnostics required. Returns true if /// the constructor declarator is invalid. void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { CXXRecordDecl *ClassDecl = dyn_cast(Constructor->getDeclContext()); if (!ClassDecl) return Constructor->setInvalidDecl(); // C++ [class.copy]p3: // A declaration of a constructor for a class X is ill-formed if // its first parameter is of type (optionally cv-qualified) X and // either there are no other parameters or else all other // parameters have default arguments. if (!Constructor->isInvalidDecl() && ((Constructor->getNumParams() == 1) || (Constructor->getNumParams() > 1 && Constructor->getParamDecl(1)->hasDefaultArg())) && Constructor->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { QualType ParamType = Constructor->getParamDecl(0)->getType(); QualType ClassTy = Context.getTagDeclType(ClassDecl); if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) { SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation(); const char *ConstRef = Constructor->getParamDecl(0)->getIdentifier() ? "const &" : " const &"; Diag(ParamLoc, diag::err_constructor_byvalue_arg) << FixItHint::CreateInsertion(ParamLoc, ConstRef); // FIXME: Rather that making the constructor invalid, we should endeavor // to fix the type. Constructor->setInvalidDecl(); } } } /// CheckDestructor - Checks a fully-formed destructor definition for /// well-formedness, issuing any diagnostics required. Returns true /// on error. bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { CXXRecordDecl *RD = Destructor->getParent(); if (!Destructor->getOperatorDelete() && Destructor->isVirtual()) { SourceLocation Loc; if (!Destructor->isImplicit()) Loc = Destructor->getLocation(); else Loc = RD->getLocation(); // If we have a virtual destructor, look up the deallocation function if (FunctionDecl *OperatorDelete = FindDeallocationFunctionForDestructor(Loc, RD)) { MarkFunctionReferenced(Loc, OperatorDelete); Destructor->setOperatorDelete(OperatorDelete); } } return false; } /// CheckDestructorDeclarator - Called by ActOnDeclarator to check /// the well-formednes of the destructor declarator @p D with type @p /// R. If there are any errors in the declarator, this routine will /// emit diagnostics and set the declarator to invalid. Even if this happens, /// will be updated to reflect a well-formed type for the destructor and /// returned. QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, StorageClass& SC) { // C++ [class.dtor]p1: // [...] A typedef-name that names a class is a class-name // (7.1.3); however, a typedef-name that names a class shall not // be used as the identifier in the declarator for a destructor // declaration. QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName); if (const TypedefType *TT = DeclaratorType->getAs()) Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) << DeclaratorType << isa(TT->getDecl()); else if (const TemplateSpecializationType *TST = DeclaratorType->getAs()) if (TST->isTypeAlias()) Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) << DeclaratorType << 1; // C++ [class.dtor]p2: // A destructor is used to destroy objects of its class type. A // destructor takes no parameters, and no return type can be // specified for it (not even void). The address of a destructor // shall not be taken. A destructor shall not be static. A // destructor can be invoked for a const, volatile or const // volatile object. A destructor shall not be declared const, // volatile or const volatile (9.3.2). if (SC == SC_Static) { if (!D.isInvalidType()) Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be) << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) << SourceRange(D.getIdentifierLoc()) << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); SC = SC_None; } if (!D.isInvalidType()) { // Destructors don't have return types, but the parser will // happily parse something like: // // class X { // float ~X(); // }; // // The return type will be eliminated later. if (D.getDeclSpec().hasTypeSpecifier()) Diag(D.getIdentifierLoc(), diag::err_destructor_return_type) << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) << SourceRange(D.getIdentifierLoc()); else if (unsigned TypeQuals = D.getDeclSpec().getTypeQualifiers()) { diagnoseIgnoredQualifiers(diag::err_destructor_return_type, TypeQuals, SourceLocation(), D.getDeclSpec().getConstSpecLoc(), D.getDeclSpec().getVolatileSpecLoc(), D.getDeclSpec().getRestrictSpecLoc(), D.getDeclSpec().getAtomicSpecLoc()); D.setInvalidType(); } } DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.TypeQuals != 0 && !D.isInvalidType()) { if (FTI.TypeQuals & Qualifiers::Const) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) << "const" << SourceRange(D.getIdentifierLoc()); if (FTI.TypeQuals & Qualifiers::Volatile) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) << "volatile" << SourceRange(D.getIdentifierLoc()); if (FTI.TypeQuals & Qualifiers::Restrict) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) << "restrict" << SourceRange(D.getIdentifierLoc()); D.setInvalidType(); } // C++0x [class.dtor]p2: // A destructor shall not be declared with a ref-qualifier. if (FTI.hasRefQualifier()) { Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_destructor) << FTI.RefQualifierIsLValueRef << FixItHint::CreateRemoval(FTI.getRefQualifierLoc()); D.setInvalidType(); } // Make sure we don't have any parameters. if (FTIHasNonVoidParameters(FTI)) { Diag(D.getIdentifierLoc(), diag::err_destructor_with_params); // Delete the parameters. FTI.freeParams(); D.setInvalidType(); } // Make sure the destructor isn't variadic. if (FTI.isVariadic) { Diag(D.getIdentifierLoc(), diag::err_destructor_variadic); D.setInvalidType(); } // Rebuild the function type "R" without any type qualifiers or // parameters (in case any of the errors above fired) and with // "void" as the return type, since destructors don't have return // types. if (!D.isInvalidType()) return R; const FunctionProtoType *Proto = R->getAs(); FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); EPI.Variadic = false; EPI.TypeQuals = 0; EPI.RefQualifier = RQ_None; return Context.getFunctionType(Context.VoidTy, None, EPI); } static void extendLeft(SourceRange &R, SourceRange Before) { if (Before.isInvalid()) return; R.setBegin(Before.getBegin()); if (R.getEnd().isInvalid()) R.setEnd(Before.getEnd()); } static void extendRight(SourceRange &R, SourceRange After) { if (After.isInvalid()) return; if (R.getBegin().isInvalid()) R.setBegin(After.getBegin()); R.setEnd(After.getEnd()); } /// CheckConversionDeclarator - Called by ActOnDeclarator to check the /// well-formednes of the conversion function declarator @p D with /// type @p R. If there are any errors in the declarator, this routine /// will emit diagnostics and return true. Otherwise, it will return /// false. Either way, the type @p R will be updated to reflect a /// well-formed type for the conversion operator. void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, StorageClass& SC) { // C++ [class.conv.fct]p1: // Neither parameter types nor return type can be specified. The // type of a conversion function (8.3.5) is "function taking no // parameter returning conversion-type-id." if (SC == SC_Static) { if (!D.isInvalidType()) Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member) << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) << D.getName().getSourceRange(); D.setInvalidType(); SC = SC_None; } TypeSourceInfo *ConvTSI = nullptr; QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId, &ConvTSI); if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) { // Conversion functions don't have return types, but the parser will // happily parse something like: // // class X { // float operator bool(); // }; // // The return type will be changed later anyway. Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type) << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) << SourceRange(D.getIdentifierLoc()); D.setInvalidType(); } const FunctionProtoType *Proto = R->getAs(); // Make sure we don't have any parameters. if (Proto->getNumParams() > 0) { Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params); // Delete the parameters. D.getFunctionTypeInfo().freeParams(); D.setInvalidType(); } else if (Proto->isVariadic()) { Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic); D.setInvalidType(); } // Diagnose "&operator bool()" and other such nonsense. This // is actually a gcc extension which we don't support. if (Proto->getReturnType() != ConvType) { bool NeedsTypedef = false; SourceRange Before, After; // Walk the chunks and extract information on them for our diagnostic. bool PastFunctionChunk = false; for (auto &Chunk : D.type_objects()) { switch (Chunk.Kind) { case DeclaratorChunk::Function: if (!PastFunctionChunk) { if (Chunk.Fun.HasTrailingReturnType) { TypeSourceInfo *TRT = nullptr; GetTypeFromParser(Chunk.Fun.getTrailingReturnType(), &TRT); if (TRT) extendRight(After, TRT->getTypeLoc().getSourceRange()); } PastFunctionChunk = true; break; } // Fall through. case DeclaratorChunk::Array: NeedsTypedef = true; extendRight(After, Chunk.getSourceRange()); break; case DeclaratorChunk::Pointer: case DeclaratorChunk::BlockPointer: case DeclaratorChunk::Reference: case DeclaratorChunk::MemberPointer: case DeclaratorChunk::Pipe: extendLeft(Before, Chunk.getSourceRange()); break; case DeclaratorChunk::Paren: extendLeft(Before, Chunk.Loc); extendRight(After, Chunk.EndLoc); break; } } SourceLocation Loc = Before.isValid() ? Before.getBegin() : After.isValid() ? After.getBegin() : D.getIdentifierLoc(); auto &&DB = Diag(Loc, diag::err_conv_function_with_complex_decl); DB << Before << After; if (!NeedsTypedef) { DB << /*don't need a typedef*/0; // If we can provide a correct fix-it hint, do so. if (After.isInvalid() && ConvTSI) { SourceLocation InsertLoc = getLocForEndOfToken(ConvTSI->getTypeLoc().getLocEnd()); DB << FixItHint::CreateInsertion(InsertLoc, " ") << FixItHint::CreateInsertionFromRange( InsertLoc, CharSourceRange::getTokenRange(Before)) << FixItHint::CreateRemoval(Before); } } else if (!Proto->getReturnType()->isDependentType()) { DB << /*typedef*/1 << Proto->getReturnType(); } else if (getLangOpts().CPlusPlus11) { DB << /*alias template*/2 << Proto->getReturnType(); } else { DB << /*might not be fixable*/3; } // Recover by incorporating the other type chunks into the result type. // Note, this does *not* change the name of the function. This is compatible // with the GCC extension: // struct S { &operator int(); } s; // int &r = s.operator int(); // ok in GCC // S::operator int&() {} // error in GCC, function name is 'operator int'. ConvType = Proto->getReturnType(); } // C++ [class.conv.fct]p4: // The conversion-type-id shall not represent a function type nor // an array type. if (ConvType->isArrayType()) { Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array); ConvType = Context.getPointerType(ConvType); D.setInvalidType(); } else if (ConvType->isFunctionType()) { Diag(D.getIdentifierLoc(), diag::err_conv_function_to_function); ConvType = Context.getPointerType(ConvType); D.setInvalidType(); } // Rebuild the function type "R" without any parameters (in case any // of the errors above fired) and with the conversion type as the // return type. if (D.isInvalidType()) R = Context.getFunctionType(ConvType, None, Proto->getExtProtoInfo()); // C++0x explicit conversion operators. if (D.getDeclSpec().isExplicitSpecified()) Diag(D.getDeclSpec().getExplicitSpecLoc(), getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_explicit_conversion_functions : diag::ext_explicit_conversion_functions) << SourceRange(D.getDeclSpec().getExplicitSpecLoc()); } /// ActOnConversionDeclarator - Called by ActOnDeclarator to complete /// the declaration of the given C++ conversion function. This routine /// is responsible for recording the conversion function in the C++ /// class, if possible. Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { assert(Conversion && "Expected to receive a conversion function declaration"); CXXRecordDecl *ClassDecl = cast(Conversion->getDeclContext()); // Make sure we aren't redeclaring the conversion function. QualType ConvType = Context.getCanonicalType(Conversion->getConversionType()); // C++ [class.conv.fct]p1: // [...] A conversion function is never used to convert a // (possibly cv-qualified) object to the (possibly cv-qualified) // same object type (or a reference to it), to a (possibly // cv-qualified) base class of that type (or a reference to it), // or to (possibly cv-qualified) void. // FIXME: Suppress this warning if the conversion function ends up being a // virtual function that overrides a virtual function in a base class. QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); if (const ReferenceType *ConvTypeRef = ConvType->getAs()) ConvType = ConvTypeRef->getPointeeType(); if (Conversion->getTemplateSpecializationKind() != TSK_Undeclared && Conversion->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) /* Suppress diagnostics for instantiations. */; else if (ConvType->isRecordType()) { ConvType = Context.getCanonicalType(ConvType).getUnqualifiedType(); if (ConvType == ClassType) Diag(Conversion->getLocation(), diag::warn_conv_to_self_not_used) << ClassType; else if (IsDerivedFrom(Conversion->getLocation(), ClassType, ConvType)) Diag(Conversion->getLocation(), diag::warn_conv_to_base_not_used) << ClassType << ConvType; } else if (ConvType->isVoidType()) { Diag(Conversion->getLocation(), diag::warn_conv_to_void_not_used) << ClassType << ConvType; } if (FunctionTemplateDecl *ConversionTemplate = Conversion->getDescribedFunctionTemplate()) return ConversionTemplate; return Conversion; } namespace { /// Utility class to accumulate and print a diagnostic listing the invalid /// specifier(s) on a declaration. struct BadSpecifierDiagnoser { BadSpecifierDiagnoser(Sema &S, SourceLocation Loc, unsigned DiagID) : S(S), Diagnostic(S.Diag(Loc, DiagID)) {} ~BadSpecifierDiagnoser() { Diagnostic << Specifiers; } template void check(SourceLocation SpecLoc, T Spec) { return check(SpecLoc, DeclSpec::getSpecifierName(Spec)); } void check(SourceLocation SpecLoc, DeclSpec::TST Spec) { return check(SpecLoc, DeclSpec::getSpecifierName(Spec, S.getPrintingPolicy())); } void check(SourceLocation SpecLoc, const char *Spec) { if (SpecLoc.isInvalid()) return; Diagnostic << SourceRange(SpecLoc, SpecLoc); if (!Specifiers.empty()) Specifiers += " "; Specifiers += Spec; } Sema &S; Sema::SemaDiagnosticBuilder Diagnostic; std::string Specifiers; }; } /// Check the validity of a declarator that we parsed for a deduction-guide. /// These aren't actually declarators in the grammar, so we need to check that /// the user didn't specify any pieces that are not part of the deduction-guide /// grammar. void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R, StorageClass &SC) { TemplateName GuidedTemplate = D.getName().TemplateName.get().get(); TemplateDecl *GuidedTemplateDecl = GuidedTemplate.getAsTemplateDecl(); assert(GuidedTemplateDecl && "missing template decl for deduction guide"); // C++ [temp.deduct.guide]p3: // A deduction-gide shall be declared in the same scope as the // corresponding class template. if (!CurContext->getRedeclContext()->Equals( GuidedTemplateDecl->getDeclContext()->getRedeclContext())) { Diag(D.getIdentifierLoc(), diag::err_deduction_guide_wrong_scope) << GuidedTemplateDecl; Diag(GuidedTemplateDecl->getLocation(), diag::note_template_decl_here); } auto &DS = D.getMutableDeclSpec(); // We leave 'friend' and 'virtual' to be rejected in the normal way. if (DS.hasTypeSpecifier() || DS.getTypeQualifiers() || DS.getStorageClassSpecLoc().isValid() || DS.isInlineSpecified() || DS.isNoreturnSpecified() || DS.isConstexprSpecified() || DS.isConceptSpecified()) { BadSpecifierDiagnoser Diagnoser( *this, D.getIdentifierLoc(), diag::err_deduction_guide_invalid_specifier); Diagnoser.check(DS.getStorageClassSpecLoc(), DS.getStorageClassSpec()); DS.ClearStorageClassSpecs(); SC = SC_None; // 'explicit' is permitted. Diagnoser.check(DS.getInlineSpecLoc(), "inline"); Diagnoser.check(DS.getNoreturnSpecLoc(), "_Noreturn"); Diagnoser.check(DS.getConstexprSpecLoc(), "constexpr"); Diagnoser.check(DS.getConceptSpecLoc(), "concept"); DS.ClearConstexprSpec(); DS.ClearConceptSpec(); Diagnoser.check(DS.getConstSpecLoc(), "const"); Diagnoser.check(DS.getRestrictSpecLoc(), "__restrict"); Diagnoser.check(DS.getVolatileSpecLoc(), "volatile"); Diagnoser.check(DS.getAtomicSpecLoc(), "_Atomic"); Diagnoser.check(DS.getUnalignedSpecLoc(), "__unaligned"); DS.ClearTypeQualifiers(); Diagnoser.check(DS.getTypeSpecComplexLoc(), DS.getTypeSpecComplex()); Diagnoser.check(DS.getTypeSpecSignLoc(), DS.getTypeSpecSign()); Diagnoser.check(DS.getTypeSpecWidthLoc(), DS.getTypeSpecWidth()); Diagnoser.check(DS.getTypeSpecTypeLoc(), DS.getTypeSpecType()); DS.ClearTypeSpecType(); } if (D.isInvalidType()) return; // Check the declarator is simple enough. bool FoundFunction = false; for (const DeclaratorChunk &Chunk : llvm::reverse(D.type_objects())) { if (Chunk.Kind == DeclaratorChunk::Paren) continue; if (Chunk.Kind != DeclaratorChunk::Function || FoundFunction) { Diag(D.getDeclSpec().getLocStart(), diag::err_deduction_guide_with_complex_decl) << D.getSourceRange(); break; } if (!Chunk.Fun.hasTrailingReturnType()) { Diag(D.getName().getLocStart(), diag::err_deduction_guide_no_trailing_return_type); break; } // Check that the return type is written as a specialization of // the template specified as the deduction-guide's name. ParsedType TrailingReturnType = Chunk.Fun.getTrailingReturnType(); TypeSourceInfo *TSI = nullptr; QualType RetTy = GetTypeFromParser(TrailingReturnType, &TSI); assert(TSI && "deduction guide has valid type but invalid return type?"); bool AcceptableReturnType = false; bool MightInstantiateToSpecialization = false; if (auto RetTST = TSI->getTypeLoc().getAs()) { TemplateName SpecifiedName = RetTST.getTypePtr()->getTemplateName(); bool TemplateMatches = Context.hasSameTemplateName(SpecifiedName, GuidedTemplate); if (SpecifiedName.getKind() == TemplateName::Template && TemplateMatches) AcceptableReturnType = true; else { // This could still instantiate to the right type, unless we know it // names the wrong class template. auto *TD = SpecifiedName.getAsTemplateDecl(); MightInstantiateToSpecialization = !(TD && isa(TD) && !TemplateMatches); } } else if (!RetTy.hasQualifiers() && RetTy->isDependentType()) { MightInstantiateToSpecialization = true; } if (!AcceptableReturnType) { Diag(TSI->getTypeLoc().getLocStart(), diag::err_deduction_guide_bad_trailing_return_type) << GuidedTemplate << TSI->getType() << MightInstantiateToSpecialization << TSI->getTypeLoc().getSourceRange(); } // Keep going to check that we don't have any inner declarator pieces (we // could still have a function returning a pointer to a function). FoundFunction = true; } if (D.isFunctionDefinition()) Diag(D.getIdentifierLoc(), diag::err_deduction_guide_defines_function); } //===----------------------------------------------------------------------===// // Namespace Handling //===----------------------------------------------------------------------===// /// \brief Diagnose a mismatch in 'inline' qualifiers when a namespace is /// reopened. static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc, SourceLocation Loc, IdentifierInfo *II, bool *IsInline, NamespaceDecl *PrevNS) { assert(*IsInline != PrevNS->isInline()); // HACK: Work around a bug in libstdc++4.6's , where // std::__atomic[0,1,2] are defined as non-inline namespaces, then reopened as // inline namespaces, with the intention of bringing names into namespace std. // // We support this just well enough to get that case working; this is not // sufficient to support reopening namespaces as inline in general. if (*IsInline && II && II->getName().startswith("__atomic") && S.getSourceManager().isInSystemHeader(Loc)) { // Mark all prior declarations of the namespace as inline. for (NamespaceDecl *NS = PrevNS->getMostRecentDecl(); NS; NS = NS->getPreviousDecl()) NS->setInline(*IsInline); // Patch up the lookup table for the containing namespace. This isn't really // correct, but it's good enough for this particular case. for (auto *I : PrevNS->decls()) if (auto *ND = dyn_cast(I)) PrevNS->getParent()->makeDeclVisibleInContext(ND); return; } if (PrevNS->isInline()) // The user probably just forgot the 'inline', so suggest that it // be added back. S.Diag(Loc, diag::warn_inline_namespace_reopened_noninline) << FixItHint::CreateInsertion(KeywordLoc, "inline "); else S.Diag(Loc, diag::err_inline_namespace_mismatch); S.Diag(PrevNS->getLocation(), diag::note_previous_definition); *IsInline = PrevNS->isInline(); } /// ActOnStartNamespaceDef - This is called at the start of a namespace /// definition. Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, SourceLocation InlineLoc, SourceLocation NamespaceLoc, SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace, AttributeList *AttrList, UsingDirectiveDecl *&UD) { SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; // For anonymous namespace, take the location of the left brace. SourceLocation Loc = II ? IdentLoc : LBrace; bool IsInline = InlineLoc.isValid(); bool IsInvalid = false; bool IsStd = false; bool AddToKnown = false; Scope *DeclRegionScope = NamespcScope->getParent(); NamespaceDecl *PrevNS = nullptr; if (II) { // C++ [namespace.def]p2: // The identifier in an original-namespace-definition shall not // have been previously defined in the declarative region in // which the original-namespace-definition appears. The // identifier in an original-namespace-definition is the name of // the namespace. Subsequently in that declarative region, it is // treated as an original-namespace-name. // // Since namespace names are unique in their scope, and we don't // look through using directives, just look for any ordinary names // as if by qualified name lookup. LookupResult R(*this, II, IdentLoc, LookupOrdinaryName, ForRedeclaration); LookupQualifiedName(R, CurContext->getRedeclContext()); NamedDecl *PrevDecl = R.isSingleResult() ? R.getRepresentativeDecl() : nullptr; PrevNS = dyn_cast_or_null(PrevDecl); if (PrevNS) { // This is an extended namespace definition. if (IsInline != PrevNS->isInline()) DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, Loc, II, &IsInline, PrevNS); } else if (PrevDecl) { // This is an invalid name redefinition. Diag(Loc, diag::err_redefinition_different_kind) << II; Diag(PrevDecl->getLocation(), diag::note_previous_definition); IsInvalid = true; // Continue on to push Namespc as current DeclContext and return it. } else if (II->isStr("std") && CurContext->getRedeclContext()->isTranslationUnit()) { // This is the first "real" definition of the namespace "std", so update // our cache of the "std" namespace to point at this definition. PrevNS = getStdNamespace(); IsStd = true; AddToKnown = !IsInline; } else { // We've seen this namespace for the first time. AddToKnown = !IsInline; } } else { // Anonymous namespaces. // Determine whether the parent already has an anonymous namespace. DeclContext *Parent = CurContext->getRedeclContext(); if (TranslationUnitDecl *TU = dyn_cast(Parent)) { PrevNS = TU->getAnonymousNamespace(); } else { NamespaceDecl *ND = cast(Parent); PrevNS = ND->getAnonymousNamespace(); } if (PrevNS && IsInline != PrevNS->isInline()) DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, NamespaceLoc, II, &IsInline, PrevNS); } NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, IsInline, StartLoc, Loc, II, PrevNS); if (IsInvalid) Namespc->setInvalidDecl(); ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); AddPragmaAttributes(DeclRegionScope, Namespc); // FIXME: Should we be merging attributes? if (const VisibilityAttr *Attr = Namespc->getAttr()) PushNamespaceVisibilityAttr(Attr, Loc); if (IsStd) StdNamespace = Namespc; if (AddToKnown) KnownNamespaces[Namespc] = false; if (II) { PushOnScopeChains(Namespc, DeclRegionScope); } else { // Link the anonymous namespace into its parent. DeclContext *Parent = CurContext->getRedeclContext(); if (TranslationUnitDecl *TU = dyn_cast(Parent)) { TU->setAnonymousNamespace(Namespc); } else { cast(Parent)->setAnonymousNamespace(Namespc); } CurContext->addDecl(Namespc); // C++ [namespace.unnamed]p1. An unnamed-namespace-definition // behaves as if it were replaced by // namespace unique { /* empty body */ } // using namespace unique; // namespace unique { namespace-body } // where all occurrences of 'unique' in a translation unit are // replaced by the same identifier and this identifier differs // from all other identifiers in the entire program. // We just create the namespace with an empty name and then add an // implicit using declaration, just like the standard suggests. // // CodeGen enforces the "universally unique" aspect by giving all // declarations semantically contained within an anonymous // namespace internal linkage. if (!PrevNS) { UD = UsingDirectiveDecl::Create(Context, Parent, /* 'using' */ LBrace, /* 'namespace' */ SourceLocation(), /* qualifier */ NestedNameSpecifierLoc(), /* identifier */ SourceLocation(), Namespc, /* Ancestor */ Parent); UD->setImplicit(); Parent->addDecl(UD); } } ActOnDocumentableDecl(Namespc); // Although we could have an invalid decl (i.e. the namespace name is a // redefinition), push it as current DeclContext and try to continue parsing. // FIXME: We should be able to push Namespc here, so that the each DeclContext // for the namespace has the declarations that showed up in that particular // namespace definition. PushDeclContext(NamespcScope, Namespc); return Namespc; } /// getNamespaceDecl - Returns the namespace a decl represents. If the decl /// is a namespace alias, returns the namespace it points to. static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) { if (NamespaceAliasDecl *AD = dyn_cast_or_null(D)) return AD->getNamespace(); return dyn_cast_or_null(D); } /// ActOnFinishNamespaceDef - This callback is called after a namespace is /// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef. void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) { NamespaceDecl *Namespc = dyn_cast_or_null(Dcl); assert(Namespc && "Invalid parameter, expected NamespaceDecl"); Namespc->setRBraceLoc(RBrace); PopDeclContext(); if (Namespc->hasAttr()) PopPragmaVisibility(true, RBrace); } CXXRecordDecl *Sema::getStdBadAlloc() const { return cast_or_null( StdBadAlloc.get(Context.getExternalSource())); } EnumDecl *Sema::getStdAlignValT() const { return cast_or_null(StdAlignValT.get(Context.getExternalSource())); } NamespaceDecl *Sema::getStdNamespace() const { return cast_or_null( StdNamespace.get(Context.getExternalSource())); } NamespaceDecl *Sema::lookupStdExperimentalNamespace() { if (!StdExperimentalNamespaceCache) { if (auto Std = getStdNamespace()) { LookupResult Result(*this, &PP.getIdentifierTable().get("experimental"), SourceLocation(), LookupNamespaceName); if (!LookupQualifiedName(Result, Std) || !(StdExperimentalNamespaceCache = Result.getAsSingle())) Result.suppressDiagnostics(); } } return StdExperimentalNamespaceCache; } /// \brief Retrieve the special "std" namespace, which may require us to /// implicitly define the namespace. NamespaceDecl *Sema::getOrCreateStdNamespace() { if (!StdNamespace) { // The "std" namespace has not yet been defined, so build one implicitly. StdNamespace = NamespaceDecl::Create(Context, Context.getTranslationUnitDecl(), /*Inline=*/false, SourceLocation(), SourceLocation(), &PP.getIdentifierTable().get("std"), /*PrevDecl=*/nullptr); getStdNamespace()->setImplicit(true); } return getStdNamespace(); } bool Sema::isStdInitializerList(QualType Ty, QualType *Element) { assert(getLangOpts().CPlusPlus && "Looking for std::initializer_list outside of C++."); // We're looking for implicit instantiations of // template class std::initializer_list. if (!StdNamespace) // If we haven't seen namespace std yet, this can't be it. return false; ClassTemplateDecl *Template = nullptr; const TemplateArgument *Arguments = nullptr; if (const RecordType *RT = Ty->getAs()) { ClassTemplateSpecializationDecl *Specialization = dyn_cast(RT->getDecl()); if (!Specialization) return false; Template = Specialization->getSpecializedTemplate(); Arguments = Specialization->getTemplateArgs().data(); } else if (const TemplateSpecializationType *TST = Ty->getAs()) { Template = dyn_cast_or_null( TST->getTemplateName().getAsTemplateDecl()); Arguments = TST->getArgs(); } if (!Template) return false; if (!StdInitializerList) { // Haven't recognized std::initializer_list yet, maybe this is it. CXXRecordDecl *TemplateClass = Template->getTemplatedDecl(); if (TemplateClass->getIdentifier() != &PP.getIdentifierTable().get("initializer_list") || !getStdNamespace()->InEnclosingNamespaceSetOf( TemplateClass->getDeclContext())) return false; // This is a template called std::initializer_list, but is it the right // template? TemplateParameterList *Params = Template->getTemplateParameters(); if (Params->getMinRequiredArguments() != 1) return false; if (!isa(Params->getParam(0))) return false; // It's the right template. StdInitializerList = Template; } if (Template->getCanonicalDecl() != StdInitializerList->getCanonicalDecl()) return false; // This is an instance of std::initializer_list. Find the argument type. if (Element) *Element = Arguments[0].getAsType(); return true; } static ClassTemplateDecl *LookupStdInitializerList(Sema &S, SourceLocation Loc){ NamespaceDecl *Std = S.getStdNamespace(); if (!Std) { S.Diag(Loc, diag::err_implied_std_initializer_list_not_found); return nullptr; } LookupResult Result(S, &S.PP.getIdentifierTable().get("initializer_list"), Loc, Sema::LookupOrdinaryName); if (!S.LookupQualifiedName(Result, Std)) { S.Diag(Loc, diag::err_implied_std_initializer_list_not_found); return nullptr; } ClassTemplateDecl *Template = Result.getAsSingle(); if (!Template) { Result.suppressDiagnostics(); // We found something weird. Complain about the first thing we found. NamedDecl *Found = *Result.begin(); S.Diag(Found->getLocation(), diag::err_malformed_std_initializer_list); return nullptr; } // We found some template called std::initializer_list. Now verify that it's // correct. TemplateParameterList *Params = Template->getTemplateParameters(); if (Params->getMinRequiredArguments() != 1 || !isa(Params->getParam(0))) { S.Diag(Template->getLocation(), diag::err_malformed_std_initializer_list); return nullptr; } return Template; } QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) { if (!StdInitializerList) { StdInitializerList = LookupStdInitializerList(*this, Loc); if (!StdInitializerList) return QualType(); } TemplateArgumentListInfo Args(Loc, Loc); Args.addArgument(TemplateArgumentLoc(TemplateArgument(Element), Context.getTrivialTypeSourceInfo(Element, Loc))); return Context.getCanonicalType( CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args)); } bool Sema::isInitListConstructor(const FunctionDecl *Ctor) { // C++ [dcl.init.list]p2: // A constructor is an initializer-list constructor if its first parameter // is of type std::initializer_list or reference to possibly cv-qualified // std::initializer_list for some type E, and either there are no other // parameters or else all other parameters have default arguments. if (Ctor->getNumParams() < 1 || (Ctor->getNumParams() > 1 && !Ctor->getParamDecl(1)->hasDefaultArg())) return false; QualType ArgType = Ctor->getParamDecl(0)->getType(); if (const ReferenceType *RT = ArgType->getAs()) ArgType = RT->getPointeeType().getUnqualifiedType(); return isStdInitializerList(ArgType, nullptr); } /// \brief Determine whether a using statement is in a context where it will be /// apply in all contexts. static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) { switch (CurContext->getDeclKind()) { case Decl::TranslationUnit: return true; case Decl::LinkageSpec: return IsUsingDirectiveInToplevelContext(CurContext->getParent()); default: return false; } } namespace { // Callback to only accept typo corrections that are namespaces. class NamespaceValidatorCCC : public CorrectionCandidateCallback { public: bool ValidateCandidate(const TypoCorrection &candidate) override { if (NamedDecl *ND = candidate.getCorrectionDecl()) return isa(ND) || isa(ND); return false; } }; } static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc, CXXScopeSpec &SS, SourceLocation IdentLoc, IdentifierInfo *Ident) { R.clear(); if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), Sc, &SS, llvm::make_unique(), Sema::CTK_ErrorRecovery)) { if (DeclContext *DC = S.computeDeclContext(SS, false)) { std::string CorrectedStr(Corrected.getAsString(S.getLangOpts())); bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && Ident->getName().equals(CorrectedStr); S.diagnoseTypo(Corrected, S.PDiag(diag::err_using_directive_member_suggest) << Ident << DC << DroppedSpecifier << SS.getRange(), S.PDiag(diag::note_namespace_defined_here)); } else { S.diagnoseTypo(Corrected, S.PDiag(diag::err_using_directive_suggest) << Ident, S.PDiag(diag::note_namespace_defined_here)); } R.addDecl(Corrected.getFoundDecl()); return true; } return false; } Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, SourceLocation NamespcLoc, CXXScopeSpec &SS, SourceLocation IdentLoc, IdentifierInfo *NamespcName, AttributeList *AttrList) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); assert(NamespcName && "Invalid NamespcName."); assert(IdentLoc.isValid() && "Invalid NamespceName location."); // This can only happen along a recovery path. while (S->isTemplateParamScope()) S = S->getParent(); assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); UsingDirectiveDecl *UDir = nullptr; NestedNameSpecifier *Qualifier = nullptr; if (SS.isSet()) Qualifier = SS.getScopeRep(); // Lookup namespace name. LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName); LookupParsedName(R, S, &SS); if (R.isAmbiguous()) return nullptr; if (R.empty()) { R.clear(); // Allow "using namespace std;" or "using namespace ::std;" even if // "std" hasn't been defined yet, for GCC compatibility. if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) && NamespcName->isStr("std")) { Diag(IdentLoc, diag::ext_using_undefined_std); R.addDecl(getOrCreateStdNamespace()); R.resolveKind(); } // Otherwise, attempt typo correction. else TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName); } if (!R.empty()) { NamedDecl *Named = R.getRepresentativeDecl(); NamespaceDecl *NS = R.getAsSingle(); assert(NS && "expected namespace decl"); // The use of a nested name specifier may trigger deprecation warnings. DiagnoseUseOfDecl(Named, IdentLoc); // C++ [namespace.udir]p1: // A using-directive specifies that the names in the nominated // namespace can be used in the scope in which the // using-directive appears after the using-directive. During // unqualified name lookup (3.4.1), the names appear as if they // were declared in the nearest enclosing namespace which // contains both the using-directive and the nominated // namespace. [Note: in this context, "contains" means "contains // directly or indirectly". ] // Find enclosing context containing both using-directive and // nominated namespace. DeclContext *CommonAncestor = cast(NS); while (CommonAncestor && !CommonAncestor->Encloses(CurContext)) CommonAncestor = CommonAncestor->getParent(); UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc, SS.getWithLocInContext(Context), IdentLoc, Named, CommonAncestor); if (IsUsingDirectiveInToplevelContext(CurContext) && !SourceMgr.isInMainFile(SourceMgr.getExpansionLoc(IdentLoc))) { Diag(IdentLoc, diag::warn_using_directive_in_header); } PushUsingDirective(S, UDir); } else { Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); } if (UDir) ProcessDeclAttributeList(S, UDir, AttrList); return UDir; } void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { // If the scope has an associated entity and the using directive is at // namespace or translation unit scope, add the UsingDirectiveDecl into // its lookup structure so qualified name lookup can find it. DeclContext *Ctx = S->getEntity(); if (Ctx && !Ctx->isFunctionOrMethod()) Ctx->addDecl(UDir); else // Otherwise, it is at block scope. The using-directives will affect lookup // only to the end of the scope. S->PushUsingDirective(UDir); } Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, SourceLocation TypenameLoc, CXXScopeSpec &SS, UnqualifiedId &Name, SourceLocation EllipsisLoc, AttributeList *AttrList) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); if (SS.isEmpty()) { Diag(Name.getLocStart(), diag::err_using_requires_qualname); return nullptr; } switch (Name.getKind()) { case UnqualifiedId::IK_ImplicitSelfParam: case UnqualifiedId::IK_Identifier: case UnqualifiedId::IK_OperatorFunctionId: case UnqualifiedId::IK_LiteralOperatorId: case UnqualifiedId::IK_ConversionFunctionId: break; case UnqualifiedId::IK_ConstructorName: case UnqualifiedId::IK_ConstructorTemplateId: // C++11 inheriting constructors. Diag(Name.getLocStart(), getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_using_decl_constructor : diag::err_using_decl_constructor) << SS.getRange(); if (getLangOpts().CPlusPlus11) break; return nullptr; case UnqualifiedId::IK_DestructorName: Diag(Name.getLocStart(), diag::err_using_decl_destructor) << SS.getRange(); return nullptr; case UnqualifiedId::IK_TemplateId: Diag(Name.getLocStart(), diag::err_using_decl_template_id) << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc); return nullptr; case UnqualifiedId::IK_DeductionGuideName: llvm_unreachable("cannot parse qualified deduction guide name"); } DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name); DeclarationName TargetName = TargetNameInfo.getName(); if (!TargetName) return nullptr; // Warn about access declarations. if (UsingLoc.isInvalid()) { Diag(Name.getLocStart(), getLangOpts().CPlusPlus11 ? diag::err_access_decl : diag::warn_access_decl_deprecated) << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using "); } if (EllipsisLoc.isInvalid()) { if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) || DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration)) return nullptr; } else { if (!SS.getScopeRep()->containsUnexpandedParameterPack() && !TargetNameInfo.containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << SourceRange(SS.getBeginLoc(), TargetNameInfo.getEndLoc()); EllipsisLoc = SourceLocation(); } } NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, TypenameLoc.isValid(), TypenameLoc, SS, TargetNameInfo, EllipsisLoc, AttrList, /*IsInstantiation*/false); if (UD) PushOnScopeChains(UD, S, /*AddToContext*/ false); return UD; } /// \brief Determine whether a using declaration considers the given /// declarations as "equivalent", e.g., if they are redeclarations of /// the same entity or are both typedefs of the same type. static bool IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2) { if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) return true; if (TypedefNameDecl *TD1 = dyn_cast(D1)) if (TypedefNameDecl *TD2 = dyn_cast(D2)) return Context.hasSameType(TD1->getUnderlyingType(), TD2->getUnderlyingType()); return false; } /// Determines whether to create a using shadow decl for a particular /// decl, given the set of decls existing prior to this using lookup. bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, const LookupResult &Previous, UsingShadowDecl *&PrevShadow) { // Diagnose finding a decl which is not from a base class of the // current class. We do this now because there are cases where this // function will silently decide not to build a shadow decl, which // will pre-empt further diagnostics. // // We don't need to do this in C++11 because we do the check once on // the qualifier. // // FIXME: diagnose the following if we care enough: // struct A { int foo; }; // struct B : A { using A::foo; }; // template struct C : A {}; // template struct D : C { using B::foo; } // <--- // This is invalid (during instantiation) in C++03 because B::foo // resolves to the using decl in B, which is not a base class of D. // We can't diagnose it immediately because C is an unknown // specialization. The UsingShadowDecl in D then points directly // to A::foo, which will look well-formed when we instantiate. // The right solution is to not collapse the shadow-decl chain. if (!getLangOpts().CPlusPlus11 && CurContext->isRecord()) { DeclContext *OrigDC = Orig->getDeclContext(); // Handle enums and anonymous structs. if (isa(OrigDC)) OrigDC = OrigDC->getParent(); CXXRecordDecl *OrigRec = cast(OrigDC); while (OrigRec->isAnonymousStructOrUnion()) OrigRec = cast(OrigRec->getDeclContext()); if (cast(CurContext)->isProvablyNotDerivedFrom(OrigRec)) { if (OrigDC == CurContext) { Diag(Using->getLocation(), diag::err_using_decl_nested_name_specifier_is_current_class) << Using->getQualifierLoc().getSourceRange(); Diag(Orig->getLocation(), diag::note_using_decl_target); Using->setInvalidDecl(); return true; } Diag(Using->getQualifierLoc().getBeginLoc(), diag::err_using_decl_nested_name_specifier_is_not_base_class) << Using->getQualifier() << cast(CurContext) << Using->getQualifierLoc().getSourceRange(); Diag(Orig->getLocation(), diag::note_using_decl_target); Using->setInvalidDecl(); return true; } } if (Previous.empty()) return false; NamedDecl *Target = Orig; if (isa(Target)) Target = cast(Target)->getTargetDecl(); // If the target happens to be one of the previous declarations, we // don't have a conflict. // // FIXME: but we might be increasing its access, in which case we // should redeclare it. NamedDecl *NonTag = nullptr, *Tag = nullptr; bool FoundEquivalentDecl = false; for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); I != E; ++I) { NamedDecl *D = (*I)->getUnderlyingDecl(); // We can have UsingDecls in our Previous results because we use the same // LookupResult for checking whether the UsingDecl itself is a valid // redeclaration. if (isa(D) || isa(D)) continue; if (IsEquivalentForUsingDecl(Context, D, Target)) { if (UsingShadowDecl *Shadow = dyn_cast(*I)) PrevShadow = Shadow; FoundEquivalentDecl = true; } else if (isEquivalentInternalLinkageDeclaration(D, Target)) { // We don't conflict with an existing using shadow decl of an equivalent // declaration, but we're not a redeclaration of it. FoundEquivalentDecl = true; } if (isVisible(D)) (isa(D) ? Tag : NonTag) = D; } if (FoundEquivalentDecl) return false; if (FunctionDecl *FD = Target->getAsFunction()) { NamedDecl *OldDecl = nullptr; switch (CheckOverload(nullptr, FD, Previous, OldDecl, /*IsForUsingDecl*/ true)) { case Ovl_Overload: return false; case Ovl_NonFunction: Diag(Using->getLocation(), diag::err_using_decl_conflict); break; // We found a decl with the exact signature. case Ovl_Match: // If we're in a record, we want to hide the target, so we // return true (without a diagnostic) to tell the caller not to // build a shadow decl. if (CurContext->isRecord()) return true; // If we're not in a record, this is an error. Diag(Using->getLocation(), diag::err_using_decl_conflict); break; } Diag(Target->getLocation(), diag::note_using_decl_target); Diag(OldDecl->getLocation(), diag::note_using_decl_conflict); Using->setInvalidDecl(); return true; } // Target is not a function. if (isa(Target)) { // No conflict between a tag and a non-tag. if (!Tag) return false; Diag(Using->getLocation(), diag::err_using_decl_conflict); Diag(Target->getLocation(), diag::note_using_decl_target); Diag(Tag->getLocation(), diag::note_using_decl_conflict); Using->setInvalidDecl(); return true; } // No conflict between a tag and a non-tag. if (!NonTag) return false; Diag(Using->getLocation(), diag::err_using_decl_conflict); Diag(Target->getLocation(), diag::note_using_decl_target); Diag(NonTag->getLocation(), diag::note_using_decl_conflict); Using->setInvalidDecl(); return true; } /// Determine whether a direct base class is a virtual base class. static bool isVirtualDirectBase(CXXRecordDecl *Derived, CXXRecordDecl *Base) { if (!Derived->getNumVBases()) return false; for (auto &B : Derived->bases()) if (B.getType()->getAsCXXRecordDecl() == Base) return B.isVirtual(); llvm_unreachable("not a direct base class"); } /// Builds a shadow declaration corresponding to a 'using' declaration. UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, UsingDecl *UD, NamedDecl *Orig, UsingShadowDecl *PrevDecl) { // If we resolved to another shadow declaration, just coalesce them. NamedDecl *Target = Orig; if (isa(Target)) { Target = cast(Target)->getTargetDecl(); assert(!isa(Target) && "nested shadow declaration"); } NamedDecl *NonTemplateTarget = Target; if (auto *TargetTD = dyn_cast(Target)) NonTemplateTarget = TargetTD->getTemplatedDecl(); UsingShadowDecl *Shadow; if (isa(NonTemplateTarget)) { bool IsVirtualBase = isVirtualDirectBase(cast(CurContext), UD->getQualifier()->getAsRecordDecl()); Shadow = ConstructorUsingShadowDecl::Create( Context, CurContext, UD->getLocation(), UD, Orig, IsVirtualBase); } else { Shadow = UsingShadowDecl::Create(Context, CurContext, UD->getLocation(), UD, Target); } UD->addShadowDecl(Shadow); Shadow->setAccess(UD->getAccess()); if (Orig->isInvalidDecl() || UD->isInvalidDecl()) Shadow->setInvalidDecl(); Shadow->setPreviousDecl(PrevDecl); if (S) PushOnScopeChains(Shadow, S); else CurContext->addDecl(Shadow); return Shadow; } /// Hides a using shadow declaration. This is required by the current /// using-decl implementation when a resolvable using declaration in a /// class is followed by a declaration which would hide or override /// one or more of the using decl's targets; for example: /// /// struct Base { void foo(int); }; /// struct Derived : Base { /// using Base::foo; /// void foo(int); /// }; /// /// The governing language is C++03 [namespace.udecl]p12: /// /// When a using-declaration brings names from a base class into a /// derived class scope, member functions in the derived class /// override and/or hide member functions with the same name and /// parameter types in a base class (rather than conflicting). /// /// There are two ways to implement this: /// (1) optimistically create shadow decls when they're not hidden /// by existing declarations, or /// (2) don't create any shadow decls (or at least don't make them /// visible) until we've fully parsed/instantiated the class. /// The problem with (1) is that we might have to retroactively remove /// a shadow decl, which requires several O(n) operations because the /// decl structures are (very reasonably) not designed for removal. /// (2) avoids this but is very fiddly and phase-dependent. void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) { if (Shadow->getDeclName().getNameKind() == DeclarationName::CXXConversionFunctionName) cast(Shadow->getDeclContext())->removeConversion(Shadow); // Remove it from the DeclContext... Shadow->getDeclContext()->removeDecl(Shadow); // ...and the scope, if applicable... if (S) { S->RemoveDecl(Shadow); IdResolver.RemoveDecl(Shadow); } // ...and the using decl. Shadow->getUsingDecl()->removeShadowDecl(Shadow); // TODO: complain somehow if Shadow was used. It shouldn't // be possible for this to happen, because...? } /// Find the base specifier for a base class with the given type. static CXXBaseSpecifier *findDirectBaseWithType(CXXRecordDecl *Derived, QualType DesiredBase, bool &AnyDependentBases) { // Check whether the named type is a direct base class. CanQualType CanonicalDesiredBase = DesiredBase->getCanonicalTypeUnqualified(); for (auto &Base : Derived->bases()) { CanQualType BaseType = Base.getType()->getCanonicalTypeUnqualified(); if (CanonicalDesiredBase == BaseType) return &Base; if (BaseType->isDependentType()) AnyDependentBases = true; } return nullptr; } namespace { class UsingValidatorCCC : public CorrectionCandidateCallback { public: UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation, NestedNameSpecifier *NNS, CXXRecordDecl *RequireMemberOf) : HasTypenameKeyword(HasTypenameKeyword), IsInstantiation(IsInstantiation), OldNNS(NNS), RequireMemberOf(RequireMemberOf) {} bool ValidateCandidate(const TypoCorrection &Candidate) override { NamedDecl *ND = Candidate.getCorrectionDecl(); // Keywords are not valid here. if (!ND || isa(ND)) return false; // Completely unqualified names are invalid for a 'using' declaration. if (Candidate.WillReplaceSpecifier() && !Candidate.getCorrectionSpecifier()) return false; // FIXME: Don't correct to a name that CheckUsingDeclRedeclaration would // reject. if (RequireMemberOf) { auto *FoundRecord = dyn_cast(ND); if (FoundRecord && FoundRecord->isInjectedClassName()) { // No-one ever wants a using-declaration to name an injected-class-name // of a base class, unless they're declaring an inheriting constructor. ASTContext &Ctx = ND->getASTContext(); if (!Ctx.getLangOpts().CPlusPlus11) return false; QualType FoundType = Ctx.getRecordType(FoundRecord); // Check that the injected-class-name is named as a member of its own // type; we don't want to suggest 'using Derived::Base;', since that // means something else. NestedNameSpecifier *Specifier = Candidate.WillReplaceSpecifier() ? Candidate.getCorrectionSpecifier() : OldNNS; if (!Specifier->getAsType() || !Ctx.hasSameType(QualType(Specifier->getAsType(), 0), FoundType)) return false; // Check that this inheriting constructor declaration actually names a // direct base class of the current class. bool AnyDependentBases = false; if (!findDirectBaseWithType(RequireMemberOf, Ctx.getRecordType(FoundRecord), AnyDependentBases) && !AnyDependentBases) return false; } else { auto *RD = dyn_cast(ND->getDeclContext()); if (!RD || RequireMemberOf->isProvablyNotDerivedFrom(RD)) return false; // FIXME: Check that the base class member is accessible? } } else { auto *FoundRecord = dyn_cast(ND); if (FoundRecord && FoundRecord->isInjectedClassName()) return false; } if (isa(ND)) return HasTypenameKeyword || !IsInstantiation; return !HasTypenameKeyword; } private: bool HasTypenameKeyword; bool IsInstantiation; NestedNameSpecifier *OldNNS; CXXRecordDecl *RequireMemberOf; }; } // end anonymous namespace /// Builds a using declaration. /// /// \param IsInstantiation - Whether this call arises from an /// instantiation of an unresolved using declaration. We treat /// the lookup differently for these declarations. NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS, DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc, AttributeList *AttrList, bool IsInstantiation) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); SourceLocation IdentLoc = NameInfo.getLoc(); assert(IdentLoc.isValid() && "Invalid TargetName location."); // FIXME: We ignore attributes for now. // For an inheriting constructor declaration, the name of the using // declaration is the name of a constructor in this class, not in the // base class. DeclarationNameInfo UsingName = NameInfo; if (UsingName.getName().getNameKind() == DeclarationName::CXXConstructorName) if (auto *RD = dyn_cast(CurContext)) UsingName.setName(Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(Context.getRecordType(RD)))); // Do the redeclaration lookup in the current scope. LookupResult Previous(*this, UsingName, LookupUsingDeclName, ForRedeclaration); Previous.setHideTags(false); if (S) { LookupName(Previous, S); // It is really dumb that we have to do this. LookupResult::Filter F = Previous.makeFilter(); while (F.hasNext()) { NamedDecl *D = F.next(); if (!isDeclInScope(D, CurContext, S)) F.erase(); // If we found a local extern declaration that's not ordinarily visible, // and this declaration is being added to a non-block scope, ignore it. // We're only checking for scope conflicts here, not also for violations // of the linkage rules. else if (!CurContext->isFunctionOrMethod() && D->isLocalExternDecl() && !(D->getIdentifierNamespace() & Decl::IDNS_Ordinary)) F.erase(); } F.done(); } else { assert(IsInstantiation && "no scope in non-instantiation"); if (CurContext->isRecord()) LookupQualifiedName(Previous, CurContext); else { // No redeclaration check is needed here; in non-member contexts we // diagnosed all possible conflicts with other using-declarations when // building the template: // // For a dependent non-type using declaration, the only valid case is // if we instantiate to a single enumerator. We check for conflicts // between shadow declarations we introduce, and we check in the template // definition for conflicts between a non-type using declaration and any // other declaration, which together covers all cases. // // A dependent typename using declaration will never successfully // instantiate, since it will always name a class member, so we reject // that in the template definition. } } // Check for invalid redeclarations. if (CheckUsingDeclRedeclaration(UsingLoc, HasTypenameKeyword, SS, IdentLoc, Previous)) return nullptr; // Check for bad qualifiers. if (CheckUsingDeclQualifier(UsingLoc, HasTypenameKeyword, SS, NameInfo, IdentLoc)) return nullptr; DeclContext *LookupContext = computeDeclContext(SS); NamedDecl *D; NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); if (!LookupContext || EllipsisLoc.isValid()) { if (HasTypenameKeyword) { // FIXME: not all declaration name kinds are legal here D = UnresolvedUsingTypenameDecl::Create(Context, CurContext, UsingLoc, TypenameLoc, QualifierLoc, IdentLoc, NameInfo.getName(), EllipsisLoc); } else { D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc, QualifierLoc, NameInfo, EllipsisLoc); } D->setAccess(AS); CurContext->addDecl(D); return D; } auto Build = [&](bool Invalid) { UsingDecl *UD = UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc, UsingName, HasTypenameKeyword); UD->setAccess(AS); CurContext->addDecl(UD); UD->setInvalidDecl(Invalid); return UD; }; auto BuildInvalid = [&]{ return Build(true); }; auto BuildValid = [&]{ return Build(false); }; if (RequireCompleteDeclContext(SS, LookupContext)) return BuildInvalid(); // Look up the target name. LookupResult R(*this, NameInfo, LookupOrdinaryName); // Unlike most lookups, we don't always want to hide tag // declarations: tag names are visible through the using declaration // even if hidden by ordinary names, *except* in a dependent context // where it's important for the sanity of two-phase lookup. if (!IsInstantiation) R.setHideTags(false); // For the purposes of this lookup, we have a base object type // equal to that of the current context. if (CurContext->isRecord()) { R.setBaseObjectType( Context.getTypeDeclType(cast(CurContext))); } LookupQualifiedName(R, LookupContext); // Try to correct typos if possible. If constructor name lookup finds no // results, that means the named class has no explicit constructors, and we // suppressed declaring implicit ones (probably because it's dependent or // invalid). if (R.empty() && NameInfo.getName().getNameKind() != DeclarationName::CXXConstructorName) { // HACK: Work around a bug in libstdc++'s detection of ::gets. Sometimes // it will believe that glibc provides a ::gets in cases where it does not, // and will try to pull it into namespace std with a using-declaration. // Just ignore the using-declaration in that case. auto *II = NameInfo.getName().getAsIdentifierInfo(); if (getLangOpts().CPlusPlus14 && II && II->isStr("gets") && CurContext->isStdNamespace() && isa(LookupContext) && getSourceManager().isInSystemHeader(UsingLoc)) return nullptr; if (TypoCorrection Corrected = CorrectTypo( R.getLookupNameInfo(), R.getLookupKind(), S, &SS, llvm::make_unique( HasTypenameKeyword, IsInstantiation, SS.getScopeRep(), dyn_cast(CurContext)), CTK_ErrorRecovery)) { // We reject candidates where DroppedSpecifier == true, hence the // literal '0' below. diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest) << NameInfo.getName() << LookupContext << 0 << SS.getRange()); // If we picked a correction with no attached Decl we can't do anything // useful with it, bail out. NamedDecl *ND = Corrected.getCorrectionDecl(); if (!ND) return BuildInvalid(); // If we corrected to an inheriting constructor, handle it as one. auto *RD = dyn_cast(ND); if (RD && RD->isInjectedClassName()) { // The parent of the injected class name is the class itself. RD = cast(RD->getParent()); // Fix up the information we'll use to build the using declaration. if (Corrected.WillReplaceSpecifier()) { NestedNameSpecifierLocBuilder Builder; Builder.MakeTrivial(Context, Corrected.getCorrectionSpecifier(), QualifierLoc.getSourceRange()); QualifierLoc = Builder.getWithLocInContext(Context); } // In this case, the name we introduce is the name of a derived class // constructor. auto *CurClass = cast(CurContext); UsingName.setName(Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(Context.getRecordType(CurClass)))); UsingName.setNamedTypeInfo(nullptr); for (auto *Ctor : LookupConstructors(RD)) R.addDecl(Ctor); R.resolveKind(); } else { // FIXME: Pick up all the declarations if we found an overloaded // function. UsingName.setName(ND->getDeclName()); R.addDecl(ND); } } else { Diag(IdentLoc, diag::err_no_member) << NameInfo.getName() << LookupContext << SS.getRange(); return BuildInvalid(); } } if (R.isAmbiguous()) return BuildInvalid(); if (HasTypenameKeyword) { // If we asked for a typename and got a non-type decl, error out. if (!R.getAsSingle()) { Diag(IdentLoc, diag::err_using_typename_non_type); for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) Diag((*I)->getUnderlyingDecl()->getLocation(), diag::note_using_decl_target); return BuildInvalid(); } } else { // If we asked for a non-typename and we got a type, error out, // but only if this is an instantiation of an unresolved using // decl. Otherwise just silently find the type name. if (IsInstantiation && R.getAsSingle()) { Diag(IdentLoc, diag::err_using_dependent_value_is_type); Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target); return BuildInvalid(); } } // C++14 [namespace.udecl]p6: // A using-declaration shall not name a namespace. if (R.getAsSingle()) { Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace) << SS.getRange(); return BuildInvalid(); } // C++14 [namespace.udecl]p7: // A using-declaration shall not name a scoped enumerator. if (auto *ED = R.getAsSingle()) { if (cast(ED->getDeclContext())->isScoped()) { Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_scoped_enum) << SS.getRange(); return BuildInvalid(); } } UsingDecl *UD = BuildValid(); // Some additional rules apply to inheriting constructors. if (UsingName.getName().getNameKind() == DeclarationName::CXXConstructorName) { // Suppress access diagnostics; the access check is instead performed at the // point of use for an inheriting constructor. R.suppressDiagnostics(); if (CheckInheritingConstructorUsingDecl(UD)) return UD; } for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { UsingShadowDecl *PrevDecl = nullptr; if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl)) BuildUsingShadowDecl(S, UD, *I, PrevDecl); } return UD; } NamedDecl *Sema::BuildUsingPackDecl(NamedDecl *InstantiatedFrom, ArrayRef Expansions) { assert(isa(InstantiatedFrom) || isa(InstantiatedFrom) || isa(InstantiatedFrom)); auto *UPD = UsingPackDecl::Create(Context, CurContext, InstantiatedFrom, Expansions); UPD->setAccess(InstantiatedFrom->getAccess()); CurContext->addDecl(UPD); return UPD; } /// Additional checks for a using declaration referring to a constructor name. bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) { assert(!UD->hasTypename() && "expecting a constructor name"); const Type *SourceType = UD->getQualifier()->getAsType(); assert(SourceType && "Using decl naming constructor doesn't have type in scope spec."); CXXRecordDecl *TargetClass = cast(CurContext); // Check whether the named type is a direct base class. bool AnyDependentBases = false; auto *Base = findDirectBaseWithType(TargetClass, QualType(SourceType, 0), AnyDependentBases); if (!Base && !AnyDependentBases) { Diag(UD->getUsingLoc(), diag::err_using_decl_constructor_not_in_direct_base) << UD->getNameInfo().getSourceRange() << QualType(SourceType, 0) << TargetClass; UD->setInvalidDecl(); return true; } if (Base) Base->setInheritConstructors(); return false; } /// Checks that the given using declaration is not an invalid /// redeclaration. Note that this is checking only for the using decl /// itself, not for any ill-formedness among the UsingShadowDecls. bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, bool HasTypenameKeyword, const CXXScopeSpec &SS, SourceLocation NameLoc, const LookupResult &Prev) { NestedNameSpecifier *Qual = SS.getScopeRep(); // C++03 [namespace.udecl]p8: // C++0x [namespace.udecl]p10: // A using-declaration is a declaration and can therefore be used // repeatedly where (and only where) multiple declarations are // allowed. // // That's in non-member contexts. if (!CurContext->getRedeclContext()->isRecord()) { // A dependent qualifier outside a class can only ever resolve to an // enumeration type. Therefore it conflicts with any other non-type // declaration in the same scope. // FIXME: How should we check for dependent type-type conflicts at block // scope? if (Qual->isDependent() && !HasTypenameKeyword) { for (auto *D : Prev) { if (!isa(D) && !isa(D) && !isa(D)) { bool OldCouldBeEnumerator = isa(D) || isa(D); Diag(NameLoc, OldCouldBeEnumerator ? diag::err_redefinition : diag::err_redefinition_different_kind) << Prev.getLookupName(); Diag(D->getLocation(), diag::note_previous_definition); return true; } } } return false; } for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) { NamedDecl *D = *I; bool DTypename; NestedNameSpecifier *DQual; if (UsingDecl *UD = dyn_cast(D)) { DTypename = UD->hasTypename(); DQual = UD->getQualifier(); } else if (UnresolvedUsingValueDecl *UD = dyn_cast(D)) { DTypename = false; DQual = UD->getQualifier(); } else if (UnresolvedUsingTypenameDecl *UD = dyn_cast(D)) { DTypename = true; DQual = UD->getQualifier(); } else continue; // using decls differ if one says 'typename' and the other doesn't. // FIXME: non-dependent using decls? if (HasTypenameKeyword != DTypename) continue; // using decls differ if they name different scopes (but note that // template instantiation can cause this check to trigger when it // didn't before instantiation). if (Context.getCanonicalNestedNameSpecifier(Qual) != Context.getCanonicalNestedNameSpecifier(DQual)) continue; Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange(); Diag(D->getLocation(), diag::note_using_decl) << 1; return true; } return false; } /// Checks that the given nested-name qualifier used in a using decl /// in the current context is appropriately related to the current /// scope. If an error is found, diagnoses it and returns true. bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, bool HasTypename, const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, SourceLocation NameLoc) { DeclContext *NamedContext = computeDeclContext(SS); if (!CurContext->isRecord()) { // C++03 [namespace.udecl]p3: // C++0x [namespace.udecl]p8: // A using-declaration for a class member shall be a member-declaration. // If we weren't able to compute a valid scope, it might validly be a // dependent class scope or a dependent enumeration unscoped scope. If // we have a 'typename' keyword, the scope must resolve to a class type. if ((HasTypename && !NamedContext) || (NamedContext && NamedContext->getRedeclContext()->isRecord())) { auto *RD = NamedContext ? cast(NamedContext->getRedeclContext()) : nullptr; if (RD && RequireCompleteDeclContext(const_cast(SS), RD)) RD = nullptr; Diag(NameLoc, diag::err_using_decl_can_not_refer_to_class_member) << SS.getRange(); // If we have a complete, non-dependent source type, try to suggest a // way to get the same effect. if (!RD) return true; // Find what this using-declaration was referring to. LookupResult R(*this, NameInfo, LookupOrdinaryName); R.setHideTags(false); R.suppressDiagnostics(); LookupQualifiedName(R, RD); if (R.getAsSingle()) { if (getLangOpts().CPlusPlus11) { // Convert 'using X::Y;' to 'using Y = X::Y;'. Diag(SS.getBeginLoc(), diag::note_using_decl_class_member_workaround) << 0 // alias declaration << FixItHint::CreateInsertion(SS.getBeginLoc(), NameInfo.getName().getAsString() + " = "); } else { // Convert 'using X::Y;' to 'typedef X::Y Y;'. SourceLocation InsertLoc = getLocForEndOfToken(NameInfo.getLocEnd()); Diag(InsertLoc, diag::note_using_decl_class_member_workaround) << 1 // typedef declaration << FixItHint::CreateReplacement(UsingLoc, "typedef") << FixItHint::CreateInsertion( InsertLoc, " " + NameInfo.getName().getAsString()); } } else if (R.getAsSingle()) { // Don't provide a fixit outside C++11 mode; we don't want to suggest // repeating the type of the static data member here. FixItHint FixIt; if (getLangOpts().CPlusPlus11) { // Convert 'using X::Y;' to 'auto &Y = X::Y;'. FixIt = FixItHint::CreateReplacement( UsingLoc, "auto &" + NameInfo.getName().getAsString() + " = "); } Diag(UsingLoc, diag::note_using_decl_class_member_workaround) << 2 // reference declaration << FixIt; } else if (R.getAsSingle()) { // Don't provide a fixit outside C++11 mode; we don't want to suggest // repeating the type of the enumeration here, and we can't do so if // the type is anonymous. FixItHint FixIt; if (getLangOpts().CPlusPlus11) { // Convert 'using X::Y;' to 'auto &Y = X::Y;'. FixIt = FixItHint::CreateReplacement( UsingLoc, "constexpr auto " + NameInfo.getName().getAsString() + " = "); } Diag(UsingLoc, diag::note_using_decl_class_member_workaround) << (getLangOpts().CPlusPlus11 ? 4 : 3) // const[expr] variable << FixIt; } return true; } // Otherwise, this might be valid. return false; } // The current scope is a record. // If the named context is dependent, we can't decide much. if (!NamedContext) { // FIXME: in C++0x, we can diagnose if we can prove that the // nested-name-specifier does not refer to a base class, which is // still possible in some cases. // Otherwise we have to conservatively report that things might be // okay. return false; } if (!NamedContext->isRecord()) { // Ideally this would point at the last name in the specifier, // but we don't have that level of source info. Diag(SS.getRange().getBegin(), diag::err_using_decl_nested_name_specifier_is_not_class) << SS.getScopeRep() << SS.getRange(); return true; } if (!NamedContext->isDependentContext() && RequireCompleteDeclContext(const_cast(SS), NamedContext)) return true; if (getLangOpts().CPlusPlus11) { // C++11 [namespace.udecl]p3: // In a using-declaration used as a member-declaration, the // nested-name-specifier shall name a base class of the class // being defined. if (cast(CurContext)->isProvablyNotDerivedFrom( cast(NamedContext))) { if (CurContext == NamedContext) { Diag(NameLoc, diag::err_using_decl_nested_name_specifier_is_current_class) << SS.getRange(); return true; } if (!cast(NamedContext)->isInvalidDecl()) { Diag(SS.getRange().getBegin(), diag::err_using_decl_nested_name_specifier_is_not_base_class) << SS.getScopeRep() << cast(CurContext) << SS.getRange(); } return true; } return false; } // C++03 [namespace.udecl]p4: // A using-declaration used as a member-declaration shall refer // to a member of a base class of the class being defined [etc.]. // Salient point: SS doesn't have to name a base class as long as // lookup only finds members from base classes. Therefore we can // diagnose here only if we can prove that that can't happen, // i.e. if the class hierarchies provably don't intersect. // TODO: it would be nice if "definitely valid" results were cached // in the UsingDecl and UsingShadowDecl so that these checks didn't // need to be repeated. llvm::SmallPtrSet Bases; auto Collect = [&Bases](const CXXRecordDecl *Base) { Bases.insert(Base); return true; }; // Collect all bases. Return false if we find a dependent base. if (!cast(CurContext)->forallBases(Collect)) return false; // Returns true if the base is dependent or is one of the accumulated base // classes. auto IsNotBase = [&Bases](const CXXRecordDecl *Base) { return !Bases.count(Base); }; // Return false if the class has a dependent base or if it or one // of its bases is present in the base set of the current context. if (Bases.count(cast(NamedContext)) || !cast(NamedContext)->forallBases(IsNotBase)) return false; Diag(SS.getRange().getBegin(), diag::err_using_decl_nested_name_specifier_is_not_base_class) << SS.getScopeRep() << cast(CurContext) << SS.getRange(); return true; } Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS, MultiTemplateParamsArg TemplateParamLists, SourceLocation UsingLoc, UnqualifiedId &Name, AttributeList *AttrList, TypeResult Type, Decl *DeclFromDeclSpec) { // Skip up to the relevant declaration scope. while (S->isTemplateParamScope()) S = S->getParent(); assert((S->getFlags() & Scope::DeclScope) && "got alias-declaration outside of declaration scope"); if (Type.isInvalid()) return nullptr; bool Invalid = false; DeclarationNameInfo NameInfo = GetNameFromUnqualifiedId(Name); TypeSourceInfo *TInfo = nullptr; GetTypeFromParser(Type.get(), &TInfo); if (DiagnoseClassNameShadow(CurContext, NameInfo)) return nullptr; if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo, UPPC_DeclarationType)) { Invalid = true; TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy, TInfo->getTypeLoc().getBeginLoc()); } LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); LookupName(Previous, S); // Warn about shadowing the name of a template parameter. if (Previous.isSingleResult() && Previous.getFoundDecl()->isTemplateParameter()) { DiagnoseTemplateParameterShadow(Name.StartLocation,Previous.getFoundDecl()); Previous.clear(); } assert(Name.Kind == UnqualifiedId::IK_Identifier && "name in alias declaration must be an identifier"); TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc, Name.StartLocation, Name.Identifier, TInfo); NewTD->setAccess(AS); if (Invalid) NewTD->setInvalidDecl(); ProcessDeclAttributeList(S, NewTD, AttrList); AddPragmaAttributes(S, NewTD); CheckTypedefForVariablyModifiedType(S, NewTD); Invalid |= NewTD->isInvalidDecl(); bool Redeclaration = false; NamedDecl *NewND; if (TemplateParamLists.size()) { TypeAliasTemplateDecl *OldDecl = nullptr; TemplateParameterList *OldTemplateParams = nullptr; if (TemplateParamLists.size() != 1) { Diag(UsingLoc, diag::err_alias_template_extra_headers) << SourceRange(TemplateParamLists[1]->getTemplateLoc(), TemplateParamLists[TemplateParamLists.size()-1]->getRAngleLoc()); } TemplateParameterList *TemplateParams = TemplateParamLists[0]; // Check that we can declare a template here. if (CheckTemplateDeclScope(S, TemplateParams)) return nullptr; // Only consider previous declarations in the same scope. FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage*/false, /*ExplicitInstantiationOrSpecialization*/false); if (!Previous.empty()) { Redeclaration = true; OldDecl = Previous.getAsSingle(); if (!OldDecl && !Invalid) { Diag(UsingLoc, diag::err_redefinition_different_kind) << Name.Identifier; NamedDecl *OldD = Previous.getRepresentativeDecl(); if (OldD->getLocation().isValid()) Diag(OldD->getLocation(), diag::note_previous_definition); Invalid = true; } if (!Invalid && OldDecl && !OldDecl->isInvalidDecl()) { if (TemplateParameterListsAreEqual(TemplateParams, OldDecl->getTemplateParameters(), /*Complain=*/true, TPL_TemplateMatch)) OldTemplateParams = OldDecl->getTemplateParameters(); else Invalid = true; TypeAliasDecl *OldTD = OldDecl->getTemplatedDecl(); if (!Invalid && !Context.hasSameType(OldTD->getUnderlyingType(), NewTD->getUnderlyingType())) { // FIXME: The C++0x standard does not clearly say this is ill-formed, // but we can't reasonably accept it. Diag(NewTD->getLocation(), diag::err_redefinition_different_typedef) << 2 << NewTD->getUnderlyingType() << OldTD->getUnderlyingType(); if (OldTD->getLocation().isValid()) Diag(OldTD->getLocation(), diag::note_previous_definition); Invalid = true; } } } // Merge any previous default template arguments into our parameters, // and check the parameter list. if (CheckTemplateParameterList(TemplateParams, OldTemplateParams, TPC_TypeAliasTemplate)) return nullptr; TypeAliasTemplateDecl *NewDecl = TypeAliasTemplateDecl::Create(Context, CurContext, UsingLoc, Name.Identifier, TemplateParams, NewTD); NewTD->setDescribedAliasTemplate(NewDecl); NewDecl->setAccess(AS); if (Invalid) NewDecl->setInvalidDecl(); else if (OldDecl) NewDecl->setPreviousDecl(OldDecl); NewND = NewDecl; } else { if (auto *TD = dyn_cast_or_null(DeclFromDeclSpec)) { setTagNameForLinkagePurposes(TD, NewTD); handleTagNumbering(TD, S); } ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration); NewND = NewTD; } PushOnScopeChains(NewND, S); ActOnDocumentableDecl(NewND); return NewND; } Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, CXXScopeSpec &SS, SourceLocation IdentLoc, IdentifierInfo *Ident) { // Lookup the namespace name. LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName); LookupParsedName(R, S, &SS); if (R.isAmbiguous()) return nullptr; if (R.empty()) { if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) { Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); return nullptr; } } assert(!R.isAmbiguous() && !R.empty()); NamedDecl *ND = R.getRepresentativeDecl(); // Check if we have a previous declaration with the same name. LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName, ForRedeclaration); LookupName(PrevR, S); // Check we're not shadowing a template parameter. if (PrevR.isSingleResult() && PrevR.getFoundDecl()->isTemplateParameter()) { DiagnoseTemplateParameterShadow(AliasLoc, PrevR.getFoundDecl()); PrevR.clear(); } // Filter out any other lookup result from an enclosing scope. FilterLookupForScope(PrevR, CurContext, S, /*ConsiderLinkage*/false, /*AllowInlineNamespace*/false); // Find the previous declaration and check that we can redeclare it. NamespaceAliasDecl *Prev = nullptr; if (PrevR.isSingleResult()) { NamedDecl *PrevDecl = PrevR.getRepresentativeDecl(); if (NamespaceAliasDecl *AD = dyn_cast(PrevDecl)) { // We already have an alias with the same name that points to the same // namespace; check that it matches. if (AD->getNamespace()->Equals(getNamespaceDecl(ND))) { Prev = AD; } else if (isVisible(PrevDecl)) { Diag(AliasLoc, diag::err_redefinition_different_namespace_alias) << Alias; Diag(AD->getLocation(), diag::note_previous_namespace_alias) << AD->getNamespace(); return nullptr; } } else if (isVisible(PrevDecl)) { unsigned DiagID = isa(PrevDecl->getUnderlyingDecl()) ? diag::err_redefinition : diag::err_redefinition_different_kind; Diag(AliasLoc, DiagID) << Alias; Diag(PrevDecl->getLocation(), diag::note_previous_definition); return nullptr; } } // The use of a nested name specifier may trigger deprecation warnings. DiagnoseUseOfDecl(ND, IdentLoc); NamespaceAliasDecl *AliasDecl = NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc, Alias, SS.getWithLocInContext(Context), IdentLoc, ND); if (Prev) AliasDecl->setPreviousDecl(Prev); PushOnScopeChains(AliasDecl, S); return AliasDecl; } namespace { struct SpecialMemberExceptionSpecInfo : SpecialMemberVisitor { SourceLocation Loc; Sema::ImplicitExceptionSpecification ExceptSpec; SpecialMemberExceptionSpecInfo(Sema &S, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, Sema::InheritedConstructorInfo *ICI, SourceLocation Loc) : SpecialMemberVisitor(S, MD, CSM, ICI), Loc(Loc), ExceptSpec(S) {} bool visitBase(CXXBaseSpecifier *Base); bool visitField(FieldDecl *FD); void visitClassSubobject(CXXRecordDecl *Class, Subobject Subobj, unsigned Quals); void visitSubobjectCall(Subobject Subobj, Sema::SpecialMemberOverloadResult SMOR); }; } bool SpecialMemberExceptionSpecInfo::visitBase(CXXBaseSpecifier *Base) { auto *RT = Base->getType()->getAs(); if (!RT) return false; auto *BaseClass = cast(RT->getDecl()); Sema::SpecialMemberOverloadResult SMOR = lookupInheritedCtor(BaseClass); if (auto *BaseCtor = SMOR.getMethod()) { visitSubobjectCall(Base, BaseCtor); return false; } visitClassSubobject(BaseClass, Base, 0); return false; } bool SpecialMemberExceptionSpecInfo::visitField(FieldDecl *FD) { if (CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer()) { Expr *E = FD->getInClassInitializer(); if (!E) // FIXME: It's a little wasteful to build and throw away a // CXXDefaultInitExpr here. // FIXME: We should have a single context note pointing at Loc, and // this location should be MD->getLocation() instead, since that's // the location where we actually use the default init expression. E = S.BuildCXXDefaultInitExpr(Loc, FD).get(); if (E) ExceptSpec.CalledExpr(E); } else if (auto *RT = S.Context.getBaseElementType(FD->getType()) ->getAs()) { visitClassSubobject(cast(RT->getDecl()), FD, FD->getType().getCVRQualifiers()); } return false; } void SpecialMemberExceptionSpecInfo::visitClassSubobject(CXXRecordDecl *Class, Subobject Subobj, unsigned Quals) { FieldDecl *Field = Subobj.dyn_cast(); bool IsMutable = Field && Field->isMutable(); visitSubobjectCall(Subobj, lookupIn(Class, Quals, IsMutable)); } void SpecialMemberExceptionSpecInfo::visitSubobjectCall( Subobject Subobj, Sema::SpecialMemberOverloadResult SMOR) { // Note, if lookup fails, it doesn't matter what exception specification we // choose because the special member will be deleted. if (CXXMethodDecl *MD = SMOR.getMethod()) ExceptSpec.CalledDecl(getSubobjectLoc(Subobj), MD); } static Sema::ImplicitExceptionSpecification ComputeDefaultedSpecialMemberExceptionSpec( Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, Sema::InheritedConstructorInfo *ICI) { CXXRecordDecl *ClassDecl = MD->getParent(); // C++ [except.spec]p14: // An implicitly declared special member function (Clause 12) shall have an // exception-specification. [...] SpecialMemberExceptionSpecInfo Info(S, MD, CSM, ICI, Loc); if (ClassDecl->isInvalidDecl()) return Info.ExceptSpec; // C++1z [except.spec]p7: // [Look for exceptions thrown by] a constructor selected [...] to // initialize a potentially constructed subobject, // C++1z [except.spec]p8: // The exception specification for an implicitly-declared destructor, or a // destructor without a noexcept-specifier, is potentially-throwing if and // only if any of the destructors for any of its potentially constructed // subojects is potentially throwing. // FIXME: We respect the first rule but ignore the "potentially constructed" // in the second rule to resolve a core issue (no number yet) that would have // us reject: // struct A { virtual void f() = 0; virtual ~A() noexcept(false) = 0; }; // struct B : A {}; // struct C : B { void f(); }; // ... due to giving B::~B() a non-throwing exception specification. Info.visit(Info.IsConstructor ? Info.VisitPotentiallyConstructedBases : Info.VisitAllBases); return Info.ExceptSpec; } namespace { /// RAII object to register a special member as being currently declared. struct DeclaringSpecialMember { Sema &S; Sema::SpecialMemberDecl D; Sema::ContextRAII SavedContext; bool WasAlreadyBeingDeclared; DeclaringSpecialMember(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM) : S(S), D(RD, CSM), SavedContext(S, RD) { WasAlreadyBeingDeclared = !S.SpecialMembersBeingDeclared.insert(D).second; if (WasAlreadyBeingDeclared) // This almost never happens, but if it does, ensure that our cache // doesn't contain a stale result. S.SpecialMemberCache.clear(); else { // Register a note to be produced if we encounter an error while // declaring the special member. Sema::CodeSynthesisContext Ctx; Ctx.Kind = Sema::CodeSynthesisContext::DeclaringSpecialMember; // FIXME: We don't have a location to use here. Using the class's // location maintains the fiction that we declare all special members // with the class, but (1) it's not clear that lying about that helps our // users understand what's going on, and (2) there may be outer contexts // on the stack (some of which are relevant) and printing them exposes // our lies. Ctx.PointOfInstantiation = RD->getLocation(); Ctx.Entity = RD; Ctx.SpecialMember = CSM; S.pushCodeSynthesisContext(Ctx); } } ~DeclaringSpecialMember() { if (!WasAlreadyBeingDeclared) { S.SpecialMembersBeingDeclared.erase(D); S.popCodeSynthesisContext(); } } /// \brief Are we already trying to declare this special member? bool isAlreadyBeingDeclared() const { return WasAlreadyBeingDeclared; } }; } void Sema::CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD) { // Look up any existing declarations, but don't trigger declaration of all // implicit special members with this name. DeclarationName Name = FD->getDeclName(); LookupResult R(*this, Name, SourceLocation(), LookupOrdinaryName, ForRedeclaration); for (auto *D : FD->getParent()->lookup(Name)) if (auto *Acceptable = R.getAcceptableDecl(D)) R.addDecl(Acceptable); R.resolveKind(); R.suppressDiagnostics(); CheckFunctionDeclaration(S, FD, R, /*IsMemberSpecialization*/false); } CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( CXXRecordDecl *ClassDecl) { // C++ [class.ctor]p5: // A default constructor for a class X is a constructor of class X // that can be called without an argument. If there is no // user-declared constructor for class X, a default constructor is // implicitly declared. An implicitly-declared default constructor // is an inline public member of its class. assert(ClassDecl->needsImplicitDefaultConstructor() && "Should not build implicit default constructor!"); DeclaringSpecialMember DSM(*this, ClassDecl, CXXDefaultConstructor); if (DSM.isAlreadyBeingDeclared()) return nullptr; bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, CXXDefaultConstructor, false); // Create the actual constructor declaration. CanQualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(ClassType); DeclarationNameInfo NameInfo(Name, ClassLoc); CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, /*Type*/QualType(), /*TInfo=*/nullptr, /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr); DefaultCon->setAccess(AS_public); DefaultCon->setDefaulted(); if (getLangOpts().CUDA) { inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDefaultConstructor, DefaultCon, /* ConstRHS */ false, /* Diagnose */ false); } // Build an exception specification pointing back at this constructor. FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, DefaultCon); DefaultCon->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); // We don't need to use SpecialMemberIsTrivial here; triviality for default // constructors is easy to compute. DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor()); // Note that we have declared this constructor. ++ASTContext::NumImplicitDefaultConstructorsDeclared; Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, DefaultCon); if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor)) SetDeclDeleted(DefaultCon, ClassLoc); if (S) PushOnScopeChains(DefaultCon, S, false); ClassDecl->addDecl(DefaultCon); return DefaultCon; } void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *Constructor) { assert((Constructor->isDefaulted() && Constructor->isDefaultConstructor() && !Constructor->doesThisDeclarationHaveABody() && !Constructor->isDeleted()) && "DefineImplicitDefaultConstructor - call it for implicit default ctor"); if (Constructor->willHaveBody() || Constructor->isInvalidDecl()) return; CXXRecordDecl *ClassDecl = Constructor->getParent(); assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); SynthesizedFunctionScope Scope(*this, Constructor); // The exception specification is needed because we are defining the // function. ResolveExceptionSpec(CurrentLocation, Constructor->getType()->castAs()); MarkVTableUsed(CurrentLocation, ClassDecl); // Add a context note for diagnostics produced after this point. Scope.addContextNote(CurrentLocation); if (SetCtorInitializers(Constructor, /*AnyErrors=*/false)) { Constructor->setInvalidDecl(); return; } SourceLocation Loc = Constructor->getLocEnd().isValid() ? Constructor->getLocEnd() : Constructor->getLocation(); Constructor->setBody(new (Context) CompoundStmt(Loc)); Constructor->markUsed(Context); if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(Constructor); } DiagnoseUninitializedFields(*this, Constructor); } void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) { // Perform any delayed checks on exception specifications. CheckDelayedMemberExceptionSpecs(); } /// Find or create the fake constructor we synthesize to model constructing an /// object of a derived class via a constructor of a base class. CXXConstructorDecl * Sema::findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *BaseCtor, ConstructorUsingShadowDecl *Shadow) { CXXRecordDecl *Derived = Shadow->getParent(); SourceLocation UsingLoc = Shadow->getLocation(); // FIXME: Add a new kind of DeclarationName for an inherited constructor. // For now we use the name of the base class constructor as a member of the // derived class to indicate a (fake) inherited constructor name. DeclarationName Name = BaseCtor->getDeclName(); // Check to see if we already have a fake constructor for this inherited // constructor call. for (NamedDecl *Ctor : Derived->lookup(Name)) if (declaresSameEntity(cast(Ctor) ->getInheritedConstructor() .getConstructor(), BaseCtor)) return cast(Ctor); DeclarationNameInfo NameInfo(Name, UsingLoc); TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(BaseCtor->getType(), UsingLoc); FunctionProtoTypeLoc ProtoLoc = TInfo->getTypeLoc().IgnoreParens().castAs(); // Check the inherited constructor is valid and find the list of base classes // from which it was inherited. InheritedConstructorInfo ICI(*this, Loc, Shadow); bool Constexpr = BaseCtor->isConstexpr() && defaultedSpecialMemberIsConstexpr(*this, Derived, CXXDefaultConstructor, false, BaseCtor, &ICI); CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create( Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo, BaseCtor->isExplicit(), /*Inline=*/true, /*ImplicitlyDeclared=*/true, Constexpr, InheritedConstructor(Shadow, BaseCtor)); if (Shadow->isInvalidDecl()) DerivedCtor->setInvalidDecl(); // Build an unevaluated exception specification for this fake constructor. const FunctionProtoType *FPT = TInfo->getType()->castAs(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExceptionSpec.Type = EST_Unevaluated; EPI.ExceptionSpec.SourceDecl = DerivedCtor; DerivedCtor->setType(Context.getFunctionType(FPT->getReturnType(), FPT->getParamTypes(), EPI)); // Build the parameter declarations. SmallVector ParamDecls; for (unsigned I = 0, N = FPT->getNumParams(); I != N; ++I) { TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(FPT->getParamType(I), UsingLoc); ParmVarDecl *PD = ParmVarDecl::Create( Context, DerivedCtor, UsingLoc, UsingLoc, /*IdentifierInfo=*/nullptr, FPT->getParamType(I), TInfo, SC_None, /*DefaultArg=*/nullptr); PD->setScopeInfo(0, I); PD->setImplicit(); // Ensure attributes are propagated onto parameters (this matters for // format, pass_object_size, ...). mergeDeclAttributes(PD, BaseCtor->getParamDecl(I)); ParamDecls.push_back(PD); ProtoLoc.setParam(I, PD); } // Set up the new constructor. assert(!BaseCtor->isDeleted() && "should not use deleted constructor"); DerivedCtor->setAccess(BaseCtor->getAccess()); DerivedCtor->setParams(ParamDecls); Derived->addDecl(DerivedCtor); if (ShouldDeleteSpecialMember(DerivedCtor, CXXDefaultConstructor, &ICI)) SetDeclDeleted(DerivedCtor, UsingLoc); return DerivedCtor; } void Sema::NoteDeletedInheritingConstructor(CXXConstructorDecl *Ctor) { InheritedConstructorInfo ICI(*this, Ctor->getLocation(), Ctor->getInheritedConstructor().getShadowDecl()); ShouldDeleteSpecialMember(Ctor, CXXDefaultConstructor, &ICI, /*Diagnose*/true); } void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *Constructor) { CXXRecordDecl *ClassDecl = Constructor->getParent(); assert(Constructor->getInheritedConstructor() && !Constructor->doesThisDeclarationHaveABody() && !Constructor->isDeleted()); if (Constructor->willHaveBody() || Constructor->isInvalidDecl()) return; // Initializations are performed "as if by a defaulted default constructor", // so enter the appropriate scope. SynthesizedFunctionScope Scope(*this, Constructor); // The exception specification is needed because we are defining the // function. ResolveExceptionSpec(CurrentLocation, Constructor->getType()->castAs()); MarkVTableUsed(CurrentLocation, ClassDecl); // Add a context note for diagnostics produced after this point. Scope.addContextNote(CurrentLocation); ConstructorUsingShadowDecl *Shadow = Constructor->getInheritedConstructor().getShadowDecl(); CXXConstructorDecl *InheritedCtor = Constructor->getInheritedConstructor().getConstructor(); // [class.inhctor.init]p1: // initialization proceeds as if a defaulted default constructor is used to // initialize the D object and each base class subobject from which the // constructor was inherited InheritedConstructorInfo ICI(*this, CurrentLocation, Shadow); CXXRecordDecl *RD = Shadow->getParent(); SourceLocation InitLoc = Shadow->getLocation(); // Build explicit initializers for all base classes from which the // constructor was inherited. SmallVector Inits; for (bool VBase : {false, true}) { for (CXXBaseSpecifier &B : VBase ? RD->vbases() : RD->bases()) { if (B.isVirtual() != VBase) continue; auto *BaseRD = B.getType()->getAsCXXRecordDecl(); if (!BaseRD) continue; auto BaseCtor = ICI.findConstructorForBase(BaseRD, InheritedCtor); if (!BaseCtor.first) continue; MarkFunctionReferenced(CurrentLocation, BaseCtor.first); ExprResult Init = new (Context) CXXInheritedCtorInitExpr( InitLoc, B.getType(), BaseCtor.first, VBase, BaseCtor.second); auto *TInfo = Context.getTrivialTypeSourceInfo(B.getType(), InitLoc); Inits.push_back(new (Context) CXXCtorInitializer( Context, TInfo, VBase, InitLoc, Init.get(), InitLoc, SourceLocation())); } } // We now proceed as if for a defaulted default constructor, with the relevant // initializers replaced. if (SetCtorInitializers(Constructor, /*AnyErrors*/false, Inits)) { Constructor->setInvalidDecl(); return; } Constructor->setBody(new (Context) CompoundStmt(InitLoc)); Constructor->markUsed(Context); if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(Constructor); } DiagnoseUninitializedFields(*this, Constructor); } CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { // C++ [class.dtor]p2: // If a class has no user-declared destructor, a destructor is // declared implicitly. An implicitly-declared destructor is an // inline public member of its class. assert(ClassDecl->needsImplicitDestructor()); DeclaringSpecialMember DSM(*this, ClassDecl, CXXDestructor); if (DSM.isAlreadyBeingDeclared()) return nullptr; // Create the actual destructor declaration. CanQualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationName Name = Context.DeclarationNames.getCXXDestructorName(ClassType); DeclarationNameInfo NameInfo(Name, ClassLoc); CXXDestructorDecl *Destructor = CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), nullptr, /*isInline=*/true, /*isImplicitlyDeclared=*/true); Destructor->setAccess(AS_public); Destructor->setDefaulted(); if (getLangOpts().CUDA) { inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDestructor, Destructor, /* ConstRHS */ false, /* Diagnose */ false); } // Build an exception specification pointing back at this destructor. FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, Destructor); Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); // We don't need to use SpecialMemberIsTrivial here; triviality for // destructors is easy to compute. Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); // Note that we have declared this destructor. ++ASTContext::NumImplicitDestructorsDeclared; Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, Destructor); // We can't check whether an implicit destructor is deleted before we complete // the definition of the class, because its validity depends on the alignment // of the class. We'll check this from ActOnFields once the class is complete. if (ClassDecl->isCompleteDefinition() && ShouldDeleteSpecialMember(Destructor, CXXDestructor)) SetDeclDeleted(Destructor, ClassLoc); // Introduce this destructor into its scope. if (S) PushOnScopeChains(Destructor, S, false); ClassDecl->addDecl(Destructor); return Destructor; } void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, CXXDestructorDecl *Destructor) { assert((Destructor->isDefaulted() && !Destructor->doesThisDeclarationHaveABody() && !Destructor->isDeleted()) && "DefineImplicitDestructor - call it for implicit default dtor"); if (Destructor->willHaveBody() || Destructor->isInvalidDecl()) return; CXXRecordDecl *ClassDecl = Destructor->getParent(); assert(ClassDecl && "DefineImplicitDestructor - invalid destructor"); SynthesizedFunctionScope Scope(*this, Destructor); // The exception specification is needed because we are defining the // function. ResolveExceptionSpec(CurrentLocation, Destructor->getType()->castAs()); MarkVTableUsed(CurrentLocation, ClassDecl); // Add a context note for diagnostics produced after this point. Scope.addContextNote(CurrentLocation); MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(), Destructor->getParent()); if (CheckDestructor(Destructor)) { Destructor->setInvalidDecl(); return; } SourceLocation Loc = Destructor->getLocEnd().isValid() ? Destructor->getLocEnd() : Destructor->getLocation(); Destructor->setBody(new (Context) CompoundStmt(Loc)); Destructor->markUsed(Context); if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(Destructor); } } /// \brief Perform any semantic analysis which needs to be delayed until all /// pending class member declarations have been parsed. void Sema::ActOnFinishCXXMemberDecls() { // If the context is an invalid C++ class, just suppress these checks. if (CXXRecordDecl *Record = dyn_cast(CurContext)) { if (Record->isInvalidDecl()) { DelayedDefaultedMemberExceptionSpecs.clear(); DelayedExceptionSpecChecks.clear(); return; } checkForMultipleExportedDefaultConstructors(*this, Record); } } void Sema::ActOnFinishCXXNonNestedClass(Decl *D) { referenceDLLExportedClassMethods(); } void Sema::referenceDLLExportedClassMethods() { if (!DelayedDllExportClasses.empty()) { // Calling ReferenceDllExportedMethods might cause the current function to // be called again, so use a local copy of DelayedDllExportClasses. SmallVector WorkList; std::swap(DelayedDllExportClasses, WorkList); for (CXXRecordDecl *Class : WorkList) ReferenceDllExportedMethods(*this, Class); } } void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, CXXDestructorDecl *Destructor) { assert(getLangOpts().CPlusPlus11 && "adjusting dtor exception specs was introduced in c++11"); // C++11 [class.dtor]p3: // A declaration of a destructor that does not have an exception- // specification is implicitly considered to have the same exception- // specification as an implicit declaration. const FunctionProtoType *DtorType = Destructor->getType()-> getAs(); if (DtorType->hasExceptionSpec()) return; // Replace the destructor's type, building off the existing one. Fortunately, // the only thing of interest in the destructor type is its extended info. // The return and arguments are fixed. FunctionProtoType::ExtProtoInfo EPI = DtorType->getExtProtoInfo(); EPI.ExceptionSpec.Type = EST_Unevaluated; EPI.ExceptionSpec.SourceDecl = Destructor; Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); // FIXME: If the destructor has a body that could throw, and the newly created // spec doesn't allow exceptions, we should emit a warning, because this // change in behavior can break conforming C++03 programs at runtime. // However, we don't have a body or an exception specification yet, so it // needs to be done somewhere else. } namespace { /// \brief An abstract base class for all helper classes used in building the // copy/move operators. These classes serve as factory functions and help us // avoid using the same Expr* in the AST twice. class ExprBuilder { ExprBuilder(const ExprBuilder&) = delete; ExprBuilder &operator=(const ExprBuilder&) = delete; protected: static Expr *assertNotNull(Expr *E) { assert(E && "Expression construction must not fail."); return E; } public: ExprBuilder() {} virtual ~ExprBuilder() {} virtual Expr *build(Sema &S, SourceLocation Loc) const = 0; }; class RefBuilder: public ExprBuilder { VarDecl *Var; QualType VarType; public: Expr *build(Sema &S, SourceLocation Loc) const override { return assertNotNull(S.BuildDeclRefExpr(Var, VarType, VK_LValue, Loc).get()); } RefBuilder(VarDecl *Var, QualType VarType) : Var(Var), VarType(VarType) {} }; class ThisBuilder: public ExprBuilder { public: Expr *build(Sema &S, SourceLocation Loc) const override { return assertNotNull(S.ActOnCXXThis(Loc).getAs()); } }; class CastBuilder: public ExprBuilder { const ExprBuilder &Builder; QualType Type; ExprValueKind Kind; const CXXCastPath &Path; public: Expr *build(Sema &S, SourceLocation Loc) const override { return assertNotNull(S.ImpCastExprToType(Builder.build(S, Loc), Type, CK_UncheckedDerivedToBase, Kind, &Path).get()); } CastBuilder(const ExprBuilder &Builder, QualType Type, ExprValueKind Kind, const CXXCastPath &Path) : Builder(Builder), Type(Type), Kind(Kind), Path(Path) {} }; class DerefBuilder: public ExprBuilder { const ExprBuilder &Builder; public: Expr *build(Sema &S, SourceLocation Loc) const override { return assertNotNull( S.CreateBuiltinUnaryOp(Loc, UO_Deref, Builder.build(S, Loc)).get()); } DerefBuilder(const ExprBuilder &Builder) : Builder(Builder) {} }; class MemberBuilder: public ExprBuilder { const ExprBuilder &Builder; QualType Type; CXXScopeSpec SS; bool IsArrow; LookupResult &MemberLookup; public: Expr *build(Sema &S, SourceLocation Loc) const override { return assertNotNull(S.BuildMemberReferenceExpr( Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(), nullptr, MemberLookup, nullptr, nullptr).get()); } MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow, LookupResult &MemberLookup) : Builder(Builder), Type(Type), IsArrow(IsArrow), MemberLookup(MemberLookup) {} }; class MoveCastBuilder: public ExprBuilder { const ExprBuilder &Builder; public: Expr *build(Sema &S, SourceLocation Loc) const override { return assertNotNull(CastForMoving(S, Builder.build(S, Loc))); } MoveCastBuilder(const ExprBuilder &Builder) : Builder(Builder) {} }; class LvalueConvBuilder: public ExprBuilder { const ExprBuilder &Builder; public: Expr *build(Sema &S, SourceLocation Loc) const override { return assertNotNull( S.DefaultLvalueConversion(Builder.build(S, Loc)).get()); } LvalueConvBuilder(const ExprBuilder &Builder) : Builder(Builder) {} }; class SubscriptBuilder: public ExprBuilder { const ExprBuilder &Base; const ExprBuilder &Index; public: Expr *build(Sema &S, SourceLocation Loc) const override { return assertNotNull(S.CreateBuiltinArraySubscriptExpr( Base.build(S, Loc), Loc, Index.build(S, Loc), Loc).get()); } SubscriptBuilder(const ExprBuilder &Base, const ExprBuilder &Index) : Base(Base), Index(Index) {} }; } // end anonymous namespace /// When generating a defaulted copy or move assignment operator, if a field /// should be copied with __builtin_memcpy rather than via explicit assignments, /// do so. This optimization only applies for arrays of scalars, and for arrays /// of class type where the selected copy/move-assignment operator is trivial. static StmtResult buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T, const ExprBuilder &ToB, const ExprBuilder &FromB) { // Compute the size of the memory buffer to be copied. QualType SizeType = S.Context.getSizeType(); llvm::APInt Size(S.Context.getTypeSize(SizeType), S.Context.getTypeSizeInChars(T).getQuantity()); // Take the address of the field references for "from" and "to". We // directly construct UnaryOperators here because semantic analysis // does not permit us to take the address of an xvalue. Expr *From = FromB.build(S, Loc); From = new (S.Context) UnaryOperator(From, UO_AddrOf, S.Context.getPointerType(From->getType()), VK_RValue, OK_Ordinary, Loc); Expr *To = ToB.build(S, Loc); To = new (S.Context) UnaryOperator(To, UO_AddrOf, S.Context.getPointerType(To->getType()), VK_RValue, OK_Ordinary, Loc); const Type *E = T->getBaseElementTypeUnsafe(); bool NeedsCollectableMemCpy = E->isRecordType() && E->getAs()->getDecl()->hasObjectMember(); // Create a reference to the __builtin_objc_memmove_collectable function StringRef MemCpyName = NeedsCollectableMemCpy ? "__builtin_objc_memmove_collectable" : "__builtin_memcpy"; LookupResult R(S, &S.Context.Idents.get(MemCpyName), Loc, Sema::LookupOrdinaryName); S.LookupName(R, S.TUScope, true); FunctionDecl *MemCpy = R.getAsSingle(); if (!MemCpy) // Something went horribly wrong earlier, and we will have complained // about it. return StmtError(); ExprResult MemCpyRef = S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy, VK_RValue, Loc, nullptr); assert(MemCpyRef.isUsable() && "Builtin reference cannot fail"); Expr *CallArgs[] = { To, From, IntegerLiteral::Create(S.Context, Size, SizeType, Loc) }; ExprResult Call = S.ActOnCallExpr(/*Scope=*/nullptr, MemCpyRef.get(), Loc, CallArgs, Loc); assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!"); return Call.getAs(); } /// \brief Builds a statement that copies/moves the given entity from \p From to /// \c To. /// /// This routine is used to copy/move the members of a class with an /// implicitly-declared copy/move assignment operator. When the entities being /// copied are arrays, this routine builds for loops to copy them. /// /// \param S The Sema object used for type-checking. /// /// \param Loc The location where the implicit copy/move is being generated. /// /// \param T The type of the expressions being copied/moved. Both expressions /// must have this type. /// /// \param To The expression we are copying/moving to. /// /// \param From The expression we are copying/moving from. /// /// \param CopyingBaseSubobject Whether we're copying/moving a base subobject. /// Otherwise, it's a non-static member subobject. /// /// \param Copying Whether we're copying or moving. /// /// \param Depth Internal parameter recording the depth of the recursion. /// /// \returns A statement or a loop that copies the expressions, or StmtResult(0) /// if a memcpy should be used instead. static StmtResult buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, const ExprBuilder &To, const ExprBuilder &From, bool CopyingBaseSubobject, bool Copying, unsigned Depth = 0) { // C++11 [class.copy]p28: // Each subobject is assigned in the manner appropriate to its type: // // - if the subobject is of class type, as if by a call to operator= with // the subobject as the object expression and the corresponding // subobject of x as a single function argument (as if by explicit // qualification; that is, ignoring any possible virtual overriding // functions in more derived classes); // // C++03 [class.copy]p13: // - if the subobject is of class type, the copy assignment operator for // the class is used (as if by explicit qualification; that is, // ignoring any possible virtual overriding functions in more derived // classes); if (const RecordType *RecordTy = T->getAs()) { CXXRecordDecl *ClassDecl = cast(RecordTy->getDecl()); // Look for operator=. DeclarationName Name = S.Context.DeclarationNames.getCXXOperatorName(OO_Equal); LookupResult OpLookup(S, Name, Loc, Sema::LookupOrdinaryName); S.LookupQualifiedName(OpLookup, ClassDecl, false); // Prior to C++11, filter out any result that isn't a copy/move-assignment // operator. if (!S.getLangOpts().CPlusPlus11) { LookupResult::Filter F = OpLookup.makeFilter(); while (F.hasNext()) { NamedDecl *D = F.next(); if (CXXMethodDecl *Method = dyn_cast(D)) if (Method->isCopyAssignmentOperator() || (!Copying && Method->isMoveAssignmentOperator())) continue; F.erase(); } F.done(); } // Suppress the protected check (C++ [class.protected]) for each of the // assignment operators we found. This strange dance is required when // we're assigning via a base classes's copy-assignment operator. To // ensure that we're getting the right base class subobject (without // ambiguities), we need to cast "this" to that subobject type; to // ensure that we don't go through the virtual call mechanism, we need // to qualify the operator= name with the base class (see below). However, // this means that if the base class has a protected copy assignment // operator, the protected member access check will fail. So, we // rewrite "protected" access to "public" access in this case, since we // know by construction that we're calling from a derived class. if (CopyingBaseSubobject) { for (LookupResult::iterator L = OpLookup.begin(), LEnd = OpLookup.end(); L != LEnd; ++L) { if (L.getAccess() == AS_protected) L.setAccess(AS_public); } } // Create the nested-name-specifier that will be used to qualify the // reference to operator=; this is required to suppress the virtual // call mechanism. CXXScopeSpec SS; const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr()); SS.MakeTrivial(S.Context, NestedNameSpecifier::Create(S.Context, nullptr, false, CanonicalT), Loc); // Create the reference to operator=. ExprResult OpEqualRef = S.BuildMemberReferenceExpr(To.build(S, Loc), T, Loc, /*isArrow=*/false, SS, /*TemplateKWLoc=*/SourceLocation(), /*FirstQualifierInScope=*/nullptr, OpLookup, /*TemplateArgs=*/nullptr, /*S*/nullptr, /*SuppressQualifierCheck=*/true); if (OpEqualRef.isInvalid()) return StmtError(); // Build the call to the assignment operator. Expr *FromInst = From.build(S, Loc); ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/nullptr, OpEqualRef.getAs(), Loc, FromInst, Loc); if (Call.isInvalid()) return StmtError(); // If we built a call to a trivial 'operator=' while copying an array, // bail out. We'll replace the whole shebang with a memcpy. CXXMemberCallExpr *CE = dyn_cast(Call.get()); if (CE && CE->getMethodDecl()->isTrivial() && Depth) return StmtResult((Stmt*)nullptr); // Convert to an expression-statement, and clean up any produced // temporaries. return S.ActOnExprStmt(Call); } // - if the subobject is of scalar type, the built-in assignment // operator is used. const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T); if (!ArrayTy) { ExprResult Assignment = S.CreateBuiltinBinOp( Loc, BO_Assign, To.build(S, Loc), From.build(S, Loc)); if (Assignment.isInvalid()) return StmtError(); return S.ActOnExprStmt(Assignment); } // - if the subobject is an array, each element is assigned, in the // manner appropriate to the element type; // Construct a loop over the array bounds, e.g., // // for (__SIZE_TYPE__ i0 = 0; i0 != array-size; ++i0) // // that will copy each of the array elements. QualType SizeType = S.Context.getSizeType(); // Create the iteration variable. IdentifierInfo *IterationVarName = nullptr; { SmallString<8> Str; llvm::raw_svector_ostream OS(Str); OS << "__i" << Depth; IterationVarName = &S.Context.Idents.get(OS.str()); } VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, IterationVarName, SizeType, S.Context.getTrivialTypeSourceInfo(SizeType, Loc), SC_None); // Initialize the iteration variable to zero. llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0); IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc)); // Creates a reference to the iteration variable. RefBuilder IterationVarRef(IterationVar, SizeType); LvalueConvBuilder IterationVarRefRVal(IterationVarRef); // Create the DeclStmt that holds the iteration variable. Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc); // Subscript the "from" and "to" expressions with the iteration variable. SubscriptBuilder FromIndexCopy(From, IterationVarRefRVal); MoveCastBuilder FromIndexMove(FromIndexCopy); const ExprBuilder *FromIndex; if (Copying) FromIndex = &FromIndexCopy; else FromIndex = &FromIndexMove; SubscriptBuilder ToIndex(To, IterationVarRefRVal); // Build the copy/move for an individual element of the array. StmtResult Copy = buildSingleCopyAssignRecursively(S, Loc, ArrayTy->getElementType(), ToIndex, *FromIndex, CopyingBaseSubobject, Copying, Depth + 1); // Bail out if copying fails or if we determined that we should use memcpy. if (Copy.isInvalid() || !Copy.get()) return Copy; // Create the comparison against the array bound. llvm::APInt Upper = ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType)); Expr *Comparison = new (S.Context) BinaryOperator(IterationVarRefRVal.build(S, Loc), IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), BO_NE, S.Context.BoolTy, VK_RValue, OK_Ordinary, Loc, FPOptions()); // Create the pre-increment of the iteration variable. Expr *Increment = new (S.Context) UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc, SizeType, VK_LValue, OK_Ordinary, Loc); // Construct the loop that copies all elements of this array. return S.ActOnForStmt( Loc, Loc, InitStmt, S.ActOnCondition(nullptr, Loc, Comparison, Sema::ConditionKind::Boolean), S.MakeFullDiscardedValueExpr(Increment), Loc, Copy.get()); } static StmtResult buildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, const ExprBuilder &To, const ExprBuilder &From, bool CopyingBaseSubobject, bool Copying) { // Maybe we should use a memcpy? if (T->isArrayType() && !T.isConstQualified() && !T.isVolatileQualified() && T.isTriviallyCopyableType(S.Context)) return buildMemcpyForAssignmentOp(S, Loc, T, To, From); StmtResult Result(buildSingleCopyAssignRecursively(S, Loc, T, To, From, CopyingBaseSubobject, Copying, 0)); // If we ended up picking a trivial assignment operator for an array of a // non-trivially-copyable class type, just emit a memcpy. if (!Result.isInvalid() && !Result.get()) return buildMemcpyForAssignmentOp(S, Loc, T, To, From); return Result; } CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { // Note: The following rules are largely analoguous to the copy // constructor rules. Note that virtual bases are not taken into account // for determining the argument type of the operator. Note also that // operators taking an object instead of a reference are allowed. assert(ClassDecl->needsImplicitCopyAssignment()); DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyAssignment); if (DSM.isAlreadyBeingDeclared()) return nullptr; QualType ArgType = Context.getTypeDeclType(ClassDecl); QualType RetType = Context.getLValueReferenceType(ArgType); bool Const = ClassDecl->implicitCopyAssignmentHasConstParam(); if (Const) ArgType = ArgType.withConst(); ArgType = Context.getLValueReferenceType(ArgType); bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, CXXCopyAssignment, Const); // An implicitly-declared copy assignment operator is an inline public // member of its class. DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationNameInfo NameInfo(Name, ClassLoc); CXXMethodDecl *CopyAssignment = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, /*StorageClass=*/SC_None, /*isInline=*/true, Constexpr, SourceLocation()); CopyAssignment->setAccess(AS_public); CopyAssignment->setDefaulted(); CopyAssignment->setImplicit(); if (getLangOpts().CUDA) { inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyAssignment, CopyAssignment, /* ConstRHS */ Const, /* Diagnose */ false); } // Build an exception specification pointing back at this member. FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, CopyAssignment); CopyAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI)); // Add the parameter to the operator. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, ClassLoc, ClassLoc, /*Id=*/nullptr, ArgType, /*TInfo=*/nullptr, SC_None, nullptr); CopyAssignment->setParams(FromParam); CopyAssignment->setTrivial( ClassDecl->needsOverloadResolutionForCopyAssignment() ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment) : ClassDecl->hasTrivialCopyAssignment()); // Note that we have added this copy-assignment operator. ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, CopyAssignment); if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment)) SetDeclDeleted(CopyAssignment, ClassLoc); if (S) PushOnScopeChains(CopyAssignment, S, false); ClassDecl->addDecl(CopyAssignment); return CopyAssignment; } /// Diagnose an implicit copy operation for a class which is odr-used, but /// which is deprecated because the class has a user-declared copy constructor, /// copy assignment operator, or destructor. static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp) { assert(CopyOp->isImplicit()); CXXRecordDecl *RD = CopyOp->getParent(); CXXMethodDecl *UserDeclaredOperation = nullptr; // In Microsoft mode, assignment operations don't affect constructors and // vice versa. if (RD->hasUserDeclaredDestructor()) { UserDeclaredOperation = RD->getDestructor(); } else if (!isa(CopyOp) && RD->hasUserDeclaredCopyConstructor() && !S.getLangOpts().MSVCCompat) { // Find any user-declared copy constructor. for (auto *I : RD->ctors()) { if (I->isCopyConstructor()) { UserDeclaredOperation = I; break; } } assert(UserDeclaredOperation); } else if (isa(CopyOp) && RD->hasUserDeclaredCopyAssignment() && !S.getLangOpts().MSVCCompat) { // Find any user-declared move assignment operator. for (auto *I : RD->methods()) { if (I->isCopyAssignmentOperator()) { UserDeclaredOperation = I; break; } } assert(UserDeclaredOperation); } if (UserDeclaredOperation) { S.Diag(UserDeclaredOperation->getLocation(), diag::warn_deprecated_copy_operation) << RD << /*copy assignment*/!isa(CopyOp) << /*destructor*/isa(UserDeclaredOperation); } } void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CXXMethodDecl *CopyAssignOperator) { assert((CopyAssignOperator->isDefaulted() && CopyAssignOperator->isOverloadedOperator() && CopyAssignOperator->getOverloadedOperator() == OO_Equal && !CopyAssignOperator->doesThisDeclarationHaveABody() && !CopyAssignOperator->isDeleted()) && "DefineImplicitCopyAssignment called for wrong function"); if (CopyAssignOperator->willHaveBody() || CopyAssignOperator->isInvalidDecl()) return; CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent(); if (ClassDecl->isInvalidDecl()) { CopyAssignOperator->setInvalidDecl(); return; } SynthesizedFunctionScope Scope(*this, CopyAssignOperator); // The exception specification is needed because we are defining the // function. ResolveExceptionSpec(CurrentLocation, CopyAssignOperator->getType()->castAs()); // Add a context note for diagnostics produced after this point. Scope.addContextNote(CurrentLocation); // C++11 [class.copy]p18: // The [definition of an implicitly declared copy assignment operator] is // deprecated if the class has a user-declared copy constructor or a // user-declared destructor. if (getLangOpts().CPlusPlus11 && CopyAssignOperator->isImplicit()) diagnoseDeprecatedCopyOperation(*this, CopyAssignOperator); // C++0x [class.copy]p30: // The implicitly-defined or explicitly-defaulted copy assignment operator // for a non-union class X performs memberwise copy assignment of its // subobjects. The direct base classes of X are assigned first, in the // order of their declaration in the base-specifier-list, and then the // immediate non-static data members of X are assigned, in the order in // which they were declared in the class definition. // The statements that form the synthesized function body. SmallVector Statements; // The parameter for the "other" object, which we are copying from. ParmVarDecl *Other = CopyAssignOperator->getParamDecl(0); Qualifiers OtherQuals = Other->getType().getQualifiers(); QualType OtherRefType = Other->getType(); if (const LValueReferenceType *OtherRef = OtherRefType->getAs()) { OtherRefType = OtherRef->getPointeeType(); OtherQuals = OtherRefType.getQualifiers(); } // Our location for everything implicitly-generated. SourceLocation Loc = CopyAssignOperator->getLocEnd().isValid() ? CopyAssignOperator->getLocEnd() : CopyAssignOperator->getLocation(); // Builds a DeclRefExpr for the "other" object. RefBuilder OtherRef(Other, OtherRefType); // Builds the "this" pointer. ThisBuilder This; // Assign base classes. bool Invalid = false; for (auto &Base : ClassDecl->bases()) { // Form the assignment: // static_cast(this)->Base::operator=(static_cast(other)); QualType BaseType = Base.getType().getUnqualifiedType(); if (!BaseType->isRecordType()) { Invalid = true; continue; } CXXCastPath BasePath; BasePath.push_back(&Base); // Construct the "from" expression, which is an implicit cast to the // appropriately-qualified base type. CastBuilder From(OtherRef, Context.getQualifiedType(BaseType, OtherQuals), VK_LValue, BasePath); // Dereference "this". DerefBuilder DerefThis(This); CastBuilder To(DerefThis, Context.getCVRQualifiedType( BaseType, CopyAssignOperator->getTypeQualifiers()), VK_LValue, BasePath); // Build the copy. StmtResult Copy = buildSingleCopyAssign(*this, Loc, BaseType, To, From, /*CopyingBaseSubobject=*/true, /*Copying=*/true); if (Copy.isInvalid()) { CopyAssignOperator->setInvalidDecl(); return; } // Success! Record the copy. Statements.push_back(Copy.getAs()); } // Assign non-static members. for (auto *Field : ClassDecl->fields()) { // FIXME: We should form some kind of AST representation for the implied // memcpy in a union copy operation. if (Field->isUnnamedBitfield() || Field->getParent()->isUnion()) continue; if (Field->isInvalidDecl()) { Invalid = true; continue; } // Check for members of reference type; we can't copy those. if (Field->getType()->isReferenceType()) { Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName(); Diag(Field->getLocation(), diag::note_declared_at); Invalid = true; continue; } // Check for members of const-qualified, non-class type. QualType BaseType = Context.getBaseElementType(Field->getType()); if (!BaseType->getAs() && BaseType.isConstQualified()) { Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName(); Diag(Field->getLocation(), diag::note_declared_at); Invalid = true; continue; } // Suppress assigning zero-width bitfields. if (Field->isBitField() && Field->getBitWidthValue(Context) == 0) continue; QualType FieldType = Field->getType().getNonReferenceType(); if (FieldType->isIncompleteArrayType()) { assert(ClassDecl->hasFlexibleArrayMember() && "Incomplete array type is not valid"); continue; } // Build references to the field in the object we're copying from and to. CXXScopeSpec SS; // Intentionally empty LookupResult MemberLookup(*this, Field->getDeclName(), Loc, LookupMemberName); MemberLookup.addDecl(Field); MemberLookup.resolveKind(); MemberBuilder From(OtherRef, OtherRefType, /*IsArrow=*/false, MemberLookup); MemberBuilder To(This, getCurrentThisType(), /*IsArrow=*/true, MemberLookup); // Build the copy of this field. StmtResult Copy = buildSingleCopyAssign(*this, Loc, FieldType, To, From, /*CopyingBaseSubobject=*/false, /*Copying=*/true); if (Copy.isInvalid()) { CopyAssignOperator->setInvalidDecl(); return; } // Success! Record the copy. Statements.push_back(Copy.getAs()); } if (!Invalid) { // Add a "return *this;" ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc)); StmtResult Return = BuildReturnStmt(Loc, ThisObj.get()); if (Return.isInvalid()) Invalid = true; else Statements.push_back(Return.getAs()); } if (Invalid) { CopyAssignOperator->setInvalidDecl(); return; } StmtResult Body; { CompoundScopeRAII CompoundScope(*this); Body = ActOnCompoundStmt(Loc, Loc, Statements, /*isStmtExpr=*/false); assert(!Body.isInvalid() && "Compound statement creation cannot fail"); } CopyAssignOperator->setBody(Body.getAs()); CopyAssignOperator->markUsed(Context); if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(CopyAssignOperator); } } CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { assert(ClassDecl->needsImplicitMoveAssignment()); DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment); if (DSM.isAlreadyBeingDeclared()) return nullptr; // Note: The following rules are largely analoguous to the move // constructor rules. QualType ArgType = Context.getTypeDeclType(ClassDecl); QualType RetType = Context.getLValueReferenceType(ArgType); ArgType = Context.getRValueReferenceType(ArgType); bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, CXXMoveAssignment, false); // An implicitly-declared move assignment operator is an inline public // member of its class. DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationNameInfo NameInfo(Name, ClassLoc); CXXMethodDecl *MoveAssignment = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, /*StorageClass=*/SC_None, /*isInline=*/true, Constexpr, SourceLocation()); MoveAssignment->setAccess(AS_public); MoveAssignment->setDefaulted(); MoveAssignment->setImplicit(); if (getLangOpts().CUDA) { inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveAssignment, MoveAssignment, /* ConstRHS */ false, /* Diagnose */ false); } // Build an exception specification pointing back at this member. FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, MoveAssignment); MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI)); // Add the parameter to the operator. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment, ClassLoc, ClassLoc, /*Id=*/nullptr, ArgType, /*TInfo=*/nullptr, SC_None, nullptr); MoveAssignment->setParams(FromParam); MoveAssignment->setTrivial( ClassDecl->needsOverloadResolutionForMoveAssignment() ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment) : ClassDecl->hasTrivialMoveAssignment()); // Note that we have added this copy-assignment operator. ++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared; Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, MoveAssignment); if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) { ClassDecl->setImplicitMoveAssignmentIsDeleted(); SetDeclDeleted(MoveAssignment, ClassLoc); } if (S) PushOnScopeChains(MoveAssignment, S, false); ClassDecl->addDecl(MoveAssignment); return MoveAssignment; } /// Check if we're implicitly defining a move assignment operator for a class /// with virtual bases. Such a move assignment might move-assign the virtual /// base multiple times. static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class, SourceLocation CurrentLocation) { assert(!Class->isDependentContext() && "should not define dependent move"); // Only a virtual base could get implicitly move-assigned multiple times. // Only a non-trivial move assignment can observe this. We only want to // diagnose if we implicitly define an assignment operator that assigns // two base classes, both of which move-assign the same virtual base. if (Class->getNumVBases() == 0 || Class->hasTrivialMoveAssignment() || Class->getNumBases() < 2) return; llvm::SmallVector Worklist; typedef llvm::DenseMap VBaseMap; VBaseMap VBases; for (auto &BI : Class->bases()) { Worklist.push_back(&BI); while (!Worklist.empty()) { CXXBaseSpecifier *BaseSpec = Worklist.pop_back_val(); CXXRecordDecl *Base = BaseSpec->getType()->getAsCXXRecordDecl(); // If the base has no non-trivial move assignment operators, // we don't care about moves from it. if (!Base->hasNonTrivialMoveAssignment()) continue; // If there's nothing virtual here, skip it. if (!BaseSpec->isVirtual() && !Base->getNumVBases()) continue; // If we're not actually going to call a move assignment for this base, // or the selected move assignment is trivial, skip it. Sema::SpecialMemberOverloadResult SMOR = S.LookupSpecialMember(Base, Sema::CXXMoveAssignment, /*ConstArg*/false, /*VolatileArg*/false, /*RValueThis*/true, /*ConstThis*/false, /*VolatileThis*/false); if (!SMOR.getMethod() || SMOR.getMethod()->isTrivial() || !SMOR.getMethod()->isMoveAssignmentOperator()) continue; if (BaseSpec->isVirtual()) { // We're going to move-assign this virtual base, and its move // assignment operator is not trivial. If this can happen for // multiple distinct direct bases of Class, diagnose it. (If it // only happens in one base, we'll diagnose it when synthesizing // that base class's move assignment operator.) CXXBaseSpecifier *&Existing = VBases.insert(std::make_pair(Base->getCanonicalDecl(), &BI)) .first->second; if (Existing && Existing != &BI) { S.Diag(CurrentLocation, diag::warn_vbase_moved_multiple_times) << Class << Base; S.Diag(Existing->getLocStart(), diag::note_vbase_moved_here) << (Base->getCanonicalDecl() == Existing->getType()->getAsCXXRecordDecl()->getCanonicalDecl()) << Base << Existing->getType() << Existing->getSourceRange(); S.Diag(BI.getLocStart(), diag::note_vbase_moved_here) << (Base->getCanonicalDecl() == BI.getType()->getAsCXXRecordDecl()->getCanonicalDecl()) << Base << BI.getType() << BaseSpec->getSourceRange(); // Only diagnose each vbase once. Existing = nullptr; } } else { // Only walk over bases that have defaulted move assignment operators. // We assume that any user-provided move assignment operator handles // the multiple-moves-of-vbase case itself somehow. if (!SMOR.getMethod()->isDefaulted()) continue; // We're going to move the base classes of Base. Add them to the list. for (auto &BI : Base->bases()) Worklist.push_back(&BI); } } } } void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, CXXMethodDecl *MoveAssignOperator) { assert((MoveAssignOperator->isDefaulted() && MoveAssignOperator->isOverloadedOperator() && MoveAssignOperator->getOverloadedOperator() == OO_Equal && !MoveAssignOperator->doesThisDeclarationHaveABody() && !MoveAssignOperator->isDeleted()) && "DefineImplicitMoveAssignment called for wrong function"); if (MoveAssignOperator->willHaveBody() || MoveAssignOperator->isInvalidDecl()) return; CXXRecordDecl *ClassDecl = MoveAssignOperator->getParent(); if (ClassDecl->isInvalidDecl()) { MoveAssignOperator->setInvalidDecl(); return; } // C++0x [class.copy]p28: // The implicitly-defined or move assignment operator for a non-union class // X performs memberwise move assignment of its subobjects. The direct base // classes of X are assigned first, in the order of their declaration in the // base-specifier-list, and then the immediate non-static data members of X // are assigned, in the order in which they were declared in the class // definition. // Issue a warning if our implicit move assignment operator will move // from a virtual base more than once. checkMoveAssignmentForRepeatedMove(*this, ClassDecl, CurrentLocation); SynthesizedFunctionScope Scope(*this, MoveAssignOperator); // The exception specification is needed because we are defining the // function. ResolveExceptionSpec(CurrentLocation, MoveAssignOperator->getType()->castAs()); // Add a context note for diagnostics produced after this point. Scope.addContextNote(CurrentLocation); // The statements that form the synthesized function body. SmallVector Statements; // The parameter for the "other" object, which we are move from. ParmVarDecl *Other = MoveAssignOperator->getParamDecl(0); QualType OtherRefType = Other->getType()-> getAs()->getPointeeType(); assert(!OtherRefType.getQualifiers() && "Bad argument type of defaulted move assignment"); // Our location for everything implicitly-generated. SourceLocation Loc = MoveAssignOperator->getLocEnd().isValid() ? MoveAssignOperator->getLocEnd() : MoveAssignOperator->getLocation(); // Builds a reference to the "other" object. RefBuilder OtherRef(Other, OtherRefType); // Cast to rvalue. MoveCastBuilder MoveOther(OtherRef); // Builds the "this" pointer. ThisBuilder This; // Assign base classes. bool Invalid = false; for (auto &Base : ClassDecl->bases()) { // C++11 [class.copy]p28: // It is unspecified whether subobjects representing virtual base classes // are assigned more than once by the implicitly-defined copy assignment // operator. // FIXME: Do not assign to a vbase that will be assigned by some other base // class. For a move-assignment, this can result in the vbase being moved // multiple times. // Form the assignment: // static_cast(this)->Base::operator=(static_cast(other)); QualType BaseType = Base.getType().getUnqualifiedType(); if (!BaseType->isRecordType()) { Invalid = true; continue; } CXXCastPath BasePath; BasePath.push_back(&Base); // Construct the "from" expression, which is an implicit cast to the // appropriately-qualified base type. CastBuilder From(OtherRef, BaseType, VK_XValue, BasePath); // Dereference "this". DerefBuilder DerefThis(This); // Implicitly cast "this" to the appropriately-qualified base type. CastBuilder To(DerefThis, Context.getCVRQualifiedType( BaseType, MoveAssignOperator->getTypeQualifiers()), VK_LValue, BasePath); // Build the move. StmtResult Move = buildSingleCopyAssign(*this, Loc, BaseType, To, From, /*CopyingBaseSubobject=*/true, /*Copying=*/false); if (Move.isInvalid()) { MoveAssignOperator->setInvalidDecl(); return; } // Success! Record the move. Statements.push_back(Move.getAs()); } // Assign non-static members. for (auto *Field : ClassDecl->fields()) { // FIXME: We should form some kind of AST representation for the implied // memcpy in a union copy operation. if (Field->isUnnamedBitfield() || Field->getParent()->isUnion()) continue; if (Field->isInvalidDecl()) { Invalid = true; continue; } // Check for members of reference type; we can't move those. if (Field->getType()->isReferenceType()) { Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName(); Diag(Field->getLocation(), diag::note_declared_at); Invalid = true; continue; } // Check for members of const-qualified, non-class type. QualType BaseType = Context.getBaseElementType(Field->getType()); if (!BaseType->getAs() && BaseType.isConstQualified()) { Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName(); Diag(Field->getLocation(), diag::note_declared_at); Invalid = true; continue; } // Suppress assigning zero-width bitfields. if (Field->isBitField() && Field->getBitWidthValue(Context) == 0) continue; QualType FieldType = Field->getType().getNonReferenceType(); if (FieldType->isIncompleteArrayType()) { assert(ClassDecl->hasFlexibleArrayMember() && "Incomplete array type is not valid"); continue; } // Build references to the field in the object we're copying from and to. LookupResult MemberLookup(*this, Field->getDeclName(), Loc, LookupMemberName); MemberLookup.addDecl(Field); MemberLookup.resolveKind(); MemberBuilder From(MoveOther, OtherRefType, /*IsArrow=*/false, MemberLookup); MemberBuilder To(This, getCurrentThisType(), /*IsArrow=*/true, MemberLookup); assert(!From.build(*this, Loc)->isLValue() && // could be xvalue or prvalue "Member reference with rvalue base must be rvalue except for reference " "members, which aren't allowed for move assignment."); // Build the move of this field. StmtResult Move = buildSingleCopyAssign(*this, Loc, FieldType, To, From, /*CopyingBaseSubobject=*/false, /*Copying=*/false); if (Move.isInvalid()) { MoveAssignOperator->setInvalidDecl(); return; } // Success! Record the copy. Statements.push_back(Move.getAs()); } if (!Invalid) { // Add a "return *this;" ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc)); StmtResult Return = BuildReturnStmt(Loc, ThisObj.get()); if (Return.isInvalid()) Invalid = true; else Statements.push_back(Return.getAs()); } if (Invalid) { MoveAssignOperator->setInvalidDecl(); return; } StmtResult Body; { CompoundScopeRAII CompoundScope(*this); Body = ActOnCompoundStmt(Loc, Loc, Statements, /*isStmtExpr=*/false); assert(!Body.isInvalid() && "Compound statement creation cannot fail"); } MoveAssignOperator->setBody(Body.getAs()); MoveAssignOperator->markUsed(Context); if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(MoveAssignOperator); } } CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( CXXRecordDecl *ClassDecl) { // C++ [class.copy]p4: // If the class definition does not explicitly declare a copy // constructor, one is declared implicitly. assert(ClassDecl->needsImplicitCopyConstructor()); DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyConstructor); if (DSM.isAlreadyBeingDeclared()) return nullptr; QualType ClassType = Context.getTypeDeclType(ClassDecl); QualType ArgType = ClassType; bool Const = ClassDecl->implicitCopyConstructorHasConstParam(); if (Const) ArgType = ArgType.withConst(); ArgType = Context.getLValueReferenceType(ArgType); bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, CXXCopyConstructor, Const); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(ClassType)); SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationNameInfo NameInfo(Name, ClassLoc); // An implicitly-declared copy constructor is an inline public // member of its class. CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr); CopyConstructor->setAccess(AS_public); CopyConstructor->setDefaulted(); if (getLangOpts().CUDA) { inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyConstructor, CopyConstructor, /* ConstRHS */ Const, /* Diagnose */ false); } // Build an exception specification pointing back at this member. FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, CopyConstructor); CopyConstructor->setType( Context.getFunctionType(Context.VoidTy, ArgType, EPI)); // Add the parameter to the constructor. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor, ClassLoc, ClassLoc, /*IdentifierInfo=*/nullptr, ArgType, /*TInfo=*/nullptr, SC_None, nullptr); CopyConstructor->setParams(FromParam); CopyConstructor->setTrivial( ClassDecl->needsOverloadResolutionForCopyConstructor() ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor) : ClassDecl->hasTrivialCopyConstructor()); // Note that we have declared this constructor. ++ASTContext::NumImplicitCopyConstructorsDeclared; Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, CopyConstructor); if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) { ClassDecl->setImplicitCopyConstructorIsDeleted(); SetDeclDeleted(CopyConstructor, ClassLoc); } if (S) PushOnScopeChains(CopyConstructor, S, false); ClassDecl->addDecl(CopyConstructor); return CopyConstructor; } void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *CopyConstructor) { assert((CopyConstructor->isDefaulted() && CopyConstructor->isCopyConstructor() && !CopyConstructor->doesThisDeclarationHaveABody() && !CopyConstructor->isDeleted()) && "DefineImplicitCopyConstructor - call it for implicit copy ctor"); if (CopyConstructor->willHaveBody() || CopyConstructor->isInvalidDecl()) return; CXXRecordDecl *ClassDecl = CopyConstructor->getParent(); assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor"); SynthesizedFunctionScope Scope(*this, CopyConstructor); // The exception specification is needed because we are defining the // function. ResolveExceptionSpec(CurrentLocation, CopyConstructor->getType()->castAs()); MarkVTableUsed(CurrentLocation, ClassDecl); // Add a context note for diagnostics produced after this point. Scope.addContextNote(CurrentLocation); // C++11 [class.copy]p7: // The [definition of an implicitly declared copy constructor] is // deprecated if the class has a user-declared copy assignment operator // or a user-declared destructor. if (getLangOpts().CPlusPlus11 && CopyConstructor->isImplicit()) diagnoseDeprecatedCopyOperation(*this, CopyConstructor); if (SetCtorInitializers(CopyConstructor, /*AnyErrors=*/false)) { CopyConstructor->setInvalidDecl(); } else { SourceLocation Loc = CopyConstructor->getLocEnd().isValid() ? CopyConstructor->getLocEnd() : CopyConstructor->getLocation(); Sema::CompoundScopeRAII CompoundScope(*this); CopyConstructor->setBody( ActOnCompoundStmt(Loc, Loc, None, /*isStmtExpr=*/false).getAs()); CopyConstructor->markUsed(Context); } if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(CopyConstructor); } } CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( CXXRecordDecl *ClassDecl) { assert(ClassDecl->needsImplicitMoveConstructor()); DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor); if (DSM.isAlreadyBeingDeclared()) return nullptr; QualType ClassType = Context.getTypeDeclType(ClassDecl); QualType ArgType = Context.getRValueReferenceType(ClassType); bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, CXXMoveConstructor, false); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(ClassType)); SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationNameInfo NameInfo(Name, ClassLoc); // C++11 [class.copy]p11: // An implicitly-declared copy/move constructor is an inline public // member of its class. CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr); MoveConstructor->setAccess(AS_public); MoveConstructor->setDefaulted(); if (getLangOpts().CUDA) { inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveConstructor, MoveConstructor, /* ConstRHS */ false, /* Diagnose */ false); } // Build an exception specification pointing back at this member. FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, MoveConstructor); MoveConstructor->setType( Context.getFunctionType(Context.VoidTy, ArgType, EPI)); // Add the parameter to the constructor. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor, ClassLoc, ClassLoc, /*IdentifierInfo=*/nullptr, ArgType, /*TInfo=*/nullptr, SC_None, nullptr); MoveConstructor->setParams(FromParam); MoveConstructor->setTrivial( ClassDecl->needsOverloadResolutionForMoveConstructor() ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor) : ClassDecl->hasTrivialMoveConstructor()); // Note that we have declared this constructor. ++ASTContext::NumImplicitMoveConstructorsDeclared; Scope *S = getScopeForContext(ClassDecl); CheckImplicitSpecialMemberDeclaration(S, MoveConstructor); if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) { ClassDecl->setImplicitMoveConstructorIsDeleted(); SetDeclDeleted(MoveConstructor, ClassLoc); } if (S) PushOnScopeChains(MoveConstructor, S, false); ClassDecl->addDecl(MoveConstructor); return MoveConstructor; } void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *MoveConstructor) { assert((MoveConstructor->isDefaulted() && MoveConstructor->isMoveConstructor() && !MoveConstructor->doesThisDeclarationHaveABody() && !MoveConstructor->isDeleted()) && "DefineImplicitMoveConstructor - call it for implicit move ctor"); if (MoveConstructor->willHaveBody() || MoveConstructor->isInvalidDecl()) return; CXXRecordDecl *ClassDecl = MoveConstructor->getParent(); assert(ClassDecl && "DefineImplicitMoveConstructor - invalid constructor"); SynthesizedFunctionScope Scope(*this, MoveConstructor); // The exception specification is needed because we are defining the // function. ResolveExceptionSpec(CurrentLocation, MoveConstructor->getType()->castAs()); MarkVTableUsed(CurrentLocation, ClassDecl); // Add a context note for diagnostics produced after this point. Scope.addContextNote(CurrentLocation); if (SetCtorInitializers(MoveConstructor, /*AnyErrors=*/false)) { MoveConstructor->setInvalidDecl(); } else { SourceLocation Loc = MoveConstructor->getLocEnd().isValid() ? MoveConstructor->getLocEnd() : MoveConstructor->getLocation(); Sema::CompoundScopeRAII CompoundScope(*this); MoveConstructor->setBody(ActOnCompoundStmt( Loc, Loc, None, /*isStmtExpr=*/ false).getAs()); MoveConstructor->markUsed(Context); } if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(MoveConstructor); } } bool Sema::isImplicitlyDeleted(FunctionDecl *FD) { return FD->isDeleted() && FD->isDefaulted() && isa(FD); } void Sema::DefineImplicitLambdaToFunctionPointerConversion( SourceLocation CurrentLocation, CXXConversionDecl *Conv) { SynthesizedFunctionScope Scope(*this, Conv); CXXRecordDecl *Lambda = Conv->getParent(); CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator(); // If we are defining a specialization of a conversion to function-ptr // cache the deduced template arguments for this specialization // so that we can use them to retrieve the corresponding call-operator // and static-invoker. const TemplateArgumentList *DeducedTemplateArgs = nullptr; // Retrieve the corresponding call-operator specialization. if (Lambda->isGenericLambda()) { assert(Conv->isFunctionTemplateSpecialization()); FunctionTemplateDecl *CallOpTemplate = CallOp->getDescribedFunctionTemplate(); DeducedTemplateArgs = Conv->getTemplateSpecializationArgs(); void *InsertPos = nullptr; FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization( DeducedTemplateArgs->asArray(), InsertPos); assert(CallOpSpec && "Conversion operator must have a corresponding call operator"); CallOp = cast(CallOpSpec); } // Mark the call operator referenced (and add to pending instantiations // if necessary). // For both the conversion and static-invoker template specializations // we construct their body's in this function, so no need to add them // to the PendingInstantiations. MarkFunctionReferenced(CurrentLocation, CallOp); // Retrieve the static invoker... CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker(); // ... and get the corresponding specialization for a generic lambda. if (Lambda->isGenericLambda()) { assert(DeducedTemplateArgs && "Must have deduced template arguments from Conversion Operator"); FunctionTemplateDecl *InvokeTemplate = Invoker->getDescribedFunctionTemplate(); void *InsertPos = nullptr; FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization( DeducedTemplateArgs->asArray(), InsertPos); assert(InvokeSpec && "Must have a corresponding static invoker specialization"); Invoker = cast(InvokeSpec); } // Construct the body of the conversion function { return __invoke; }. Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(), VK_LValue, Conv->getLocation()).get(); assert(FunctionRef && "Can't refer to __invoke function?"); Stmt *Return = BuildReturnStmt(Conv->getLocation(), FunctionRef).get(); Conv->setBody(new (Context) CompoundStmt(Context, Return, Conv->getLocation(), Conv->getLocation())); Conv->markUsed(Context); Conv->setReferenced(); // Fill in the __invoke function with a dummy implementation. IR generation // will fill in the actual details. Invoker->markUsed(Context); Invoker->setReferenced(); Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation())); if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(Conv); L->CompletedImplicitDefinition(Invoker); } } void Sema::DefineImplicitLambdaToBlockPointerConversion( SourceLocation CurrentLocation, CXXConversionDecl *Conv) { assert(!Conv->getParent()->isGenericLambda()); SynthesizedFunctionScope Scope(*this, Conv); // Copy-initialize the lambda object as needed to capture it. Expr *This = ActOnCXXThis(CurrentLocation).get(); Expr *DerefThis =CreateBuiltinUnaryOp(CurrentLocation, UO_Deref, This).get(); ExprResult BuildBlock = BuildBlockForLambdaConversion(CurrentLocation, Conv->getLocation(), Conv, DerefThis); // If we're not under ARC, make sure we still get the _Block_copy/autorelease // behavior. Note that only the general conversion function does this // (since it's unusable otherwise); in the case where we inline the // block literal, it has block literal lifetime semantics. if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount) BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(), CK_CopyAndAutoreleaseBlockObject, BuildBlock.get(), nullptr, VK_RValue); if (BuildBlock.isInvalid()) { Diag(CurrentLocation, diag::note_lambda_to_block_conv); Conv->setInvalidDecl(); return; } // Create the return statement that returns the block from the conversion // function. StmtResult Return = BuildReturnStmt(Conv->getLocation(), BuildBlock.get()); if (Return.isInvalid()) { Diag(CurrentLocation, diag::note_lambda_to_block_conv); Conv->setInvalidDecl(); return; } // Set the body of the conversion function. Stmt *ReturnS = Return.get(); Conv->setBody(new (Context) CompoundStmt(Context, ReturnS, Conv->getLocation(), Conv->getLocation())); Conv->markUsed(Context); // We're done; notify the mutation listener, if any. if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(Conv); } } /// \brief Determine whether the given list arguments contains exactly one /// "real" (non-default) argument. static bool hasOneRealArgument(MultiExprArg Args) { switch (Args.size()) { case 0: return false; default: if (!Args[1]->isDefaultArgument()) return false; // fall through case 1: return !Args[0]->isDefaultArgument(); } return false; } ExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, NamedDecl *FoundDecl, CXXConstructorDecl *Constructor, MultiExprArg ExprArgs, bool HadMultipleCandidates, bool IsListInitialization, bool IsStdInitListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { bool Elidable = false; // C++0x [class.copy]p34: // When certain criteria are met, an implementation is allowed to // omit the copy/move construction of a class object, even if the // copy/move constructor and/or destructor for the object have // side effects. [...] // - when a temporary class object that has not been bound to a // reference (12.2) would be copied/moved to a class object // with the same cv-unqualified type, the copy/move operation // can be omitted by constructing the temporary object // directly into the target of the omitted copy/move if (ConstructKind == CXXConstructExpr::CK_Complete && Constructor && Constructor->isCopyOrMoveConstructor() && hasOneRealArgument(ExprArgs)) { Expr *SubExpr = ExprArgs[0]; Elidable = SubExpr->isTemporaryObject( Context, cast(FoundDecl->getDeclContext())); } return BuildCXXConstructExpr(ConstructLoc, DeclInitType, FoundDecl, Constructor, Elidable, ExprArgs, HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, RequiresZeroInit, ConstructKind, ParenRange); } ExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, NamedDecl *FoundDecl, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg ExprArgs, bool HadMultipleCandidates, bool IsListInitialization, bool IsStdInitListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { if (auto *Shadow = dyn_cast(FoundDecl)) { Constructor = findInheritingConstructor(ConstructLoc, Constructor, Shadow); if (DiagnoseUseOfDecl(Constructor, ConstructLoc)) return ExprError(); } return BuildCXXConstructExpr( ConstructLoc, DeclInitType, Constructor, Elidable, ExprArgs, HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, RequiresZeroInit, ConstructKind, ParenRange); } /// BuildCXXConstructExpr - Creates a complete call to a constructor, /// including handling of its default argument expressions. ExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg ExprArgs, bool HadMultipleCandidates, bool IsListInitialization, bool IsStdInitListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { assert(declaresSameEntity( Constructor->getParent(), DeclInitType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) && "given constructor for wrong type"); MarkFunctionReferenced(ConstructLoc, Constructor); if (getLangOpts().CUDA && !CheckCUDACall(ConstructLoc, Constructor)) return ExprError(); return CXXConstructExpr::Create( Context, DeclInitType, ConstructLoc, Constructor, Elidable, ExprArgs, HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, RequiresZeroInit, static_cast(ConstructKind), ParenRange); } ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { assert(Field->hasInClassInitializer()); // If we already have the in-class initializer nothing needs to be done. if (Field->getInClassInitializer()) return CXXDefaultInitExpr::Create(Context, Loc, Field); // If we might have already tried and failed to instantiate, don't try again. if (Field->isInvalidDecl()) return ExprError(); // Maybe we haven't instantiated the in-class initializer. Go check the // pattern FieldDecl to see if it has one. CXXRecordDecl *ParentRD = cast(Field->getParent()); if (isTemplateInstantiation(ParentRD->getTemplateSpecializationKind())) { CXXRecordDecl *ClassPattern = ParentRD->getTemplateInstantiationPattern(); DeclContext::lookup_result Lookup = ClassPattern->lookup(Field->getDeclName()); // Lookup can return at most two results: the pattern for the field, or the // injected class name of the parent record. No other member can have the // same name as the field. // In modules mode, lookup can return multiple results (coming from // different modules). assert((getLangOpts().Modules || (!Lookup.empty() && Lookup.size() <= 2)) && "more than two lookup results for field name"); FieldDecl *Pattern = dyn_cast(Lookup[0]); if (!Pattern) { assert(isa(Lookup[0]) && "cannot have other non-field member with same name"); for (auto L : Lookup) if (isa(L)) { Pattern = cast(L); break; } assert(Pattern && "We must have set the Pattern!"); } if (InstantiateInClassInitializer(Loc, Field, Pattern, getTemplateInstantiationArgs(Field))) { // Don't diagnose this again. Field->setInvalidDecl(); return ExprError(); } return CXXDefaultInitExpr::Create(Context, Loc, Field); } // DR1351: // If the brace-or-equal-initializer of a non-static data member // invokes a defaulted default constructor of its class or of an // enclosing class in a potentially evaluated subexpression, the // program is ill-formed. // // This resolution is unworkable: the exception specification of the // default constructor can be needed in an unevaluated context, in // particular, in the operand of a noexcept-expression, and we can be // unable to compute an exception specification for an enclosed class. // // Any attempt to resolve the exception specification of a defaulted default // constructor before the initializer is lexically complete will ultimately // come here at which point we can diagnose it. RecordDecl *OutermostClass = ParentRD->getOuterLexicalRecordContext(); Diag(Loc, diag::err_in_class_initializer_not_yet_parsed) << OutermostClass << Field; Diag(Field->getLocEnd(), diag::note_in_class_initializer_not_yet_parsed); // Recover by marking the field invalid, unless we're in a SFINAE context. if (!isSFINAEContext()) Field->setInvalidDecl(); return ExprError(); } void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { if (VD->isInvalidDecl()) return; CXXRecordDecl *ClassDecl = cast(Record->getDecl()); if (ClassDecl->isInvalidDecl()) return; if (ClassDecl->hasIrrelevantDestructor()) return; if (ClassDecl->isDependentContext()) return; CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); MarkFunctionReferenced(VD->getLocation(), Destructor); CheckDestructorAccess(VD->getLocation(), Destructor, PDiag(diag::err_access_dtor_var) << VD->getDeclName() << VD->getType()); DiagnoseUseOfDecl(Destructor, VD->getLocation()); if (Destructor->isTrivial()) return; if (!VD->hasGlobalStorage()) return; // Emit warning for non-trivial dtor in global scope (a real global, // class-static, function-static). Diag(VD->getLocation(), diag::warn_exit_time_destructor); // TODO: this should be re-enabled for static locals by !CXAAtExit if (!VD->isStaticLocal()) Diag(VD->getLocation(), diag::warn_global_destructor); } /// \brief Given a constructor and the set of arguments provided for the /// constructor, convert the arguments and add any required default arguments /// to form a proper call to this constructor. /// /// \returns true if an error occurred, false otherwise. bool Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, MultiExprArg ArgsPtr, SourceLocation Loc, SmallVectorImpl &ConvertedArgs, bool AllowExplicit, bool IsListInitialization) { // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall. unsigned NumArgs = ArgsPtr.size(); Expr **Args = ArgsPtr.data(); const FunctionProtoType *Proto = Constructor->getType()->getAs(); assert(Proto && "Constructor without a prototype?"); unsigned NumParams = Proto->getNumParams(); // If too few arguments are available, we'll fill in the rest with defaults. if (NumArgs < NumParams) ConvertedArgs.reserve(NumParams); else ConvertedArgs.reserve(NumArgs); VariadicCallType CallType = Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply; SmallVector AllArgs; bool Invalid = GatherArgumentsForCall(Loc, Constructor, Proto, 0, llvm::makeArrayRef(Args, NumArgs), AllArgs, CallType, AllowExplicit, IsListInitialization); ConvertedArgs.append(AllArgs.begin(), AllArgs.end()); DiagnoseSentinelCalls(Constructor, Loc, AllArgs); CheckConstructorCall(Constructor, llvm::makeArrayRef(AllArgs.data(), AllArgs.size()), Proto, Loc); return Invalid; } static inline bool CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef, const FunctionDecl *FnDecl) { const DeclContext *DC = FnDecl->getDeclContext()->getRedeclContext(); if (isa(DC)) { return SemaRef.Diag(FnDecl->getLocation(), diag::err_operator_new_delete_declared_in_namespace) << FnDecl->getDeclName(); } if (isa(DC) && FnDecl->getStorageClass() == SC_Static) { return SemaRef.Diag(FnDecl->getLocation(), diag::err_operator_new_delete_declared_static) << FnDecl->getDeclName(); } return false; } static inline bool CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, CanQualType ExpectedResultType, CanQualType ExpectedFirstParamType, unsigned DependentParamTypeDiag, unsigned InvalidParamTypeDiag) { QualType ResultType = FnDecl->getType()->getAs()->getReturnType(); // Check that the result type is not dependent. if (ResultType->isDependentType()) return SemaRef.Diag(FnDecl->getLocation(), diag::err_operator_new_delete_dependent_result_type) << FnDecl->getDeclName() << ExpectedResultType; // Check that the result type is what we expect. if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType) return SemaRef.Diag(FnDecl->getLocation(), diag::err_operator_new_delete_invalid_result_type) << FnDecl->getDeclName() << ExpectedResultType; // A function template must have at least 2 parameters. if (FnDecl->getDescribedFunctionTemplate() && FnDecl->getNumParams() < 2) return SemaRef.Diag(FnDecl->getLocation(), diag::err_operator_new_delete_template_too_few_parameters) << FnDecl->getDeclName(); // The function decl must have at least 1 parameter. if (FnDecl->getNumParams() == 0) return SemaRef.Diag(FnDecl->getLocation(), diag::err_operator_new_delete_too_few_parameters) << FnDecl->getDeclName(); // Check the first parameter type is not dependent. QualType FirstParamType = FnDecl->getParamDecl(0)->getType(); if (FirstParamType->isDependentType()) return SemaRef.Diag(FnDecl->getLocation(), DependentParamTypeDiag) << FnDecl->getDeclName() << ExpectedFirstParamType; // Check that the first parameter type is what we expect. if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() != ExpectedFirstParamType) return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag) << FnDecl->getDeclName() << ExpectedFirstParamType; return false; } static bool CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) { // C++ [basic.stc.dynamic.allocation]p1: // A program is ill-formed if an allocation function is declared in a // namespace scope other than global scope or declared static in global // scope. if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl)) return true; CanQualType SizeTy = SemaRef.Context.getCanonicalType(SemaRef.Context.getSizeType()); // C++ [basic.stc.dynamic.allocation]p1: // The return type shall be void*. The first parameter shall have type // std::size_t. if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidPtrTy, SizeTy, diag::err_operator_new_dependent_param_type, diag::err_operator_new_param_type)) return true; // C++ [basic.stc.dynamic.allocation]p1: // The first parameter shall not have an associated default argument. if (FnDecl->getParamDecl(0)->hasDefaultArg()) return SemaRef.Diag(FnDecl->getLocation(), diag::err_operator_new_default_arg) << FnDecl->getDeclName() << FnDecl->getParamDecl(0)->getDefaultArgRange(); return false; } static bool CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) { // C++ [basic.stc.dynamic.deallocation]p1: // A program is ill-formed if deallocation functions are declared in a // namespace scope other than global scope or declared static in global // scope. if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl)) return true; // C++ [basic.stc.dynamic.deallocation]p2: // Each deallocation function shall return void and its first parameter // shall be void*. if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidTy, SemaRef.Context.VoidPtrTy, diag::err_operator_delete_dependent_param_type, diag::err_operator_delete_param_type)) return true; return false; } /// CheckOverloadedOperatorDeclaration - Check whether the declaration /// of this overloaded operator is well-formed. If so, returns false; /// otherwise, emits appropriate diagnostics and returns true. bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { assert(FnDecl && FnDecl->isOverloadedOperator() && "Expected an overloaded operator declaration"); OverloadedOperatorKind Op = FnDecl->getOverloadedOperator(); // C++ [over.oper]p5: // The allocation and deallocation functions, operator new, // operator new[], operator delete and operator delete[], are // described completely in 3.7.3. The attributes and restrictions // found in the rest of this subclause do not apply to them unless // explicitly stated in 3.7.3. if (Op == OO_Delete || Op == OO_Array_Delete) return CheckOperatorDeleteDeclaration(*this, FnDecl); if (Op == OO_New || Op == OO_Array_New) return CheckOperatorNewDeclaration(*this, FnDecl); // C++ [over.oper]p6: // An operator function shall either be a non-static member // function or be a non-member function and have at least one // parameter whose type is a class, a reference to a class, an // enumeration, or a reference to an enumeration. if (CXXMethodDecl *MethodDecl = dyn_cast(FnDecl)) { if (MethodDecl->isStatic()) return Diag(FnDecl->getLocation(), diag::err_operator_overload_static) << FnDecl->getDeclName(); } else { bool ClassOrEnumParam = false; for (auto Param : FnDecl->parameters()) { QualType ParamType = Param->getType().getNonReferenceType(); if (ParamType->isDependentType() || ParamType->isRecordType() || ParamType->isEnumeralType()) { ClassOrEnumParam = true; break; } } if (!ClassOrEnumParam) return Diag(FnDecl->getLocation(), diag::err_operator_overload_needs_class_or_enum) << FnDecl->getDeclName(); } // C++ [over.oper]p8: // An operator function cannot have default arguments (8.3.6), // except where explicitly stated below. // // Only the function-call operator allows default arguments // (C++ [over.call]p1). if (Op != OO_Call) { for (auto Param : FnDecl->parameters()) { if (Param->hasDefaultArg()) return Diag(Param->getLocation(), diag::err_operator_overload_default_arg) << FnDecl->getDeclName() << Param->getDefaultArgRange(); } } static const bool OperatorUses[NUM_OVERLOADED_OPERATORS][3] = { { false, false, false } #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ , { Unary, Binary, MemberOnly } #include "clang/Basic/OperatorKinds.def" }; bool CanBeUnaryOperator = OperatorUses[Op][0]; bool CanBeBinaryOperator = OperatorUses[Op][1]; bool MustBeMemberOperator = OperatorUses[Op][2]; // C++ [over.oper]p8: // [...] Operator functions cannot have more or fewer parameters // than the number required for the corresponding operator, as // described in the rest of this subclause. unsigned NumParams = FnDecl->getNumParams() + (isa(FnDecl)? 1 : 0); if (Op != OO_Call && ((NumParams == 1 && !CanBeUnaryOperator) || (NumParams == 2 && !CanBeBinaryOperator) || (NumParams < 1) || (NumParams > 2))) { // We have the wrong number of parameters. unsigned ErrorKind; if (CanBeUnaryOperator && CanBeBinaryOperator) { ErrorKind = 2; // 2 -> unary or binary. } else if (CanBeUnaryOperator) { ErrorKind = 0; // 0 -> unary } else { assert(CanBeBinaryOperator && "All non-call overloaded operators are unary or binary!"); ErrorKind = 1; // 1 -> binary } return Diag(FnDecl->getLocation(), diag::err_operator_overload_must_be) << FnDecl->getDeclName() << NumParams << ErrorKind; } // Overloaded operators other than operator() cannot be variadic. if (Op != OO_Call && FnDecl->getType()->getAs()->isVariadic()) { return Diag(FnDecl->getLocation(), diag::err_operator_overload_variadic) << FnDecl->getDeclName(); } // Some operators must be non-static member functions. if (MustBeMemberOperator && !isa(FnDecl)) { return Diag(FnDecl->getLocation(), diag::err_operator_overload_must_be_member) << FnDecl->getDeclName(); } // C++ [over.inc]p1: // The user-defined function called operator++ implements the // prefix and postfix ++ operator. If this function is a member // function with no parameters, or a non-member function with one // parameter of class or enumeration type, it defines the prefix // increment operator ++ for objects of that type. If the function // is a member function with one parameter (which shall be of type // int) or a non-member function with two parameters (the second // of which shall be of type int), it defines the postfix // increment operator ++ for objects of that type. if ((Op == OO_PlusPlus || Op == OO_MinusMinus) && NumParams == 2) { ParmVarDecl *LastParam = FnDecl->getParamDecl(FnDecl->getNumParams() - 1); QualType ParamType = LastParam->getType(); if (!ParamType->isSpecificBuiltinType(BuiltinType::Int) && !ParamType->isDependentType()) return Diag(LastParam->getLocation(), diag::err_operator_overload_post_incdec_must_be_int) << LastParam->getType() << (Op == OO_MinusMinus); } return false; } static bool checkLiteralOperatorTemplateParameterList(Sema &SemaRef, FunctionTemplateDecl *TpDecl) { TemplateParameterList *TemplateParams = TpDecl->getTemplateParameters(); // Must have one or two template parameters. if (TemplateParams->size() == 1) { NonTypeTemplateParmDecl *PmDecl = dyn_cast(TemplateParams->getParam(0)); // The template parameter must be a char parameter pack. if (PmDecl && PmDecl->isTemplateParameterPack() && SemaRef.Context.hasSameType(PmDecl->getType(), SemaRef.Context.CharTy)) return false; } else if (TemplateParams->size() == 2) { TemplateTypeParmDecl *PmType = dyn_cast(TemplateParams->getParam(0)); NonTypeTemplateParmDecl *PmArgs = dyn_cast(TemplateParams->getParam(1)); // The second template parameter must be a parameter pack with the // first template parameter as its type. if (PmType && PmArgs && !PmType->isTemplateParameterPack() && PmArgs->isTemplateParameterPack()) { const TemplateTypeParmType *TArgs = PmArgs->getType()->getAs(); if (TArgs && TArgs->getDepth() == PmType->getDepth() && TArgs->getIndex() == PmType->getIndex()) { if (!SemaRef.inTemplateInstantiation()) SemaRef.Diag(TpDecl->getLocation(), diag::ext_string_literal_operator_template); return false; } } } SemaRef.Diag(TpDecl->getTemplateParameters()->getSourceRange().getBegin(), diag::err_literal_operator_template) << TpDecl->getTemplateParameters()->getSourceRange(); return true; } /// CheckLiteralOperatorDeclaration - Check whether the declaration /// of this literal operator function is well-formed. If so, returns /// false; otherwise, emits appropriate diagnostics and returns true. bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { if (isa(FnDecl)) { Diag(FnDecl->getLocation(), diag::err_literal_operator_outside_namespace) << FnDecl->getDeclName(); return true; } if (FnDecl->isExternC()) { Diag(FnDecl->getLocation(), diag::err_literal_operator_extern_c); if (const LinkageSpecDecl *LSD = FnDecl->getDeclContext()->getExternCContext()) Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here); return true; } // This might be the definition of a literal operator template. FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate(); // This might be a specialization of a literal operator template. if (!TpDecl) TpDecl = FnDecl->getPrimaryTemplate(); // template type operator "" name() and // template type operator "" name() are the only valid // template signatures, and the only valid signatures with no parameters. if (TpDecl) { if (FnDecl->param_size() != 0) { Diag(FnDecl->getLocation(), diag::err_literal_operator_template_with_params); return true; } if (checkLiteralOperatorTemplateParameterList(*this, TpDecl)) return true; } else if (FnDecl->param_size() == 1) { const ParmVarDecl *Param = FnDecl->getParamDecl(0); QualType ParamType = Param->getType().getUnqualifiedType(); // Only unsigned long long int, long double, any character type, and const // char * are allowed as the only parameters. if (ParamType->isSpecificBuiltinType(BuiltinType::ULongLong) || ParamType->isSpecificBuiltinType(BuiltinType::LongDouble) || Context.hasSameType(ParamType, Context.CharTy) || Context.hasSameType(ParamType, Context.WideCharTy) || Context.hasSameType(ParamType, Context.Char16Ty) || Context.hasSameType(ParamType, Context.Char32Ty)) { } else if (const PointerType *Ptr = ParamType->getAs()) { QualType InnerType = Ptr->getPointeeType(); // Pointer parameter must be a const char *. if (!(Context.hasSameType(InnerType.getUnqualifiedType(), Context.CharTy) && InnerType.isConstQualified() && !InnerType.isVolatileQualified())) { Diag(Param->getSourceRange().getBegin(), diag::err_literal_operator_param) << ParamType << "'const char *'" << Param->getSourceRange(); return true; } } else if (ParamType->isRealFloatingType()) { Diag(Param->getSourceRange().getBegin(), diag::err_literal_operator_param) << ParamType << Context.LongDoubleTy << Param->getSourceRange(); return true; } else if (ParamType->isIntegerType()) { Diag(Param->getSourceRange().getBegin(), diag::err_literal_operator_param) << ParamType << Context.UnsignedLongLongTy << Param->getSourceRange(); return true; } else { Diag(Param->getSourceRange().getBegin(), diag::err_literal_operator_invalid_param) << ParamType << Param->getSourceRange(); return true; } } else if (FnDecl->param_size() == 2) { FunctionDecl::param_iterator Param = FnDecl->param_begin(); // First, verify that the first parameter is correct. QualType FirstParamType = (*Param)->getType().getUnqualifiedType(); // Two parameter function must have a pointer to const as a // first parameter; let's strip those qualifiers. const PointerType *PT = FirstParamType->getAs(); if (!PT) { Diag((*Param)->getSourceRange().getBegin(), diag::err_literal_operator_param) << FirstParamType << "'const char *'" << (*Param)->getSourceRange(); return true; } QualType PointeeType = PT->getPointeeType(); // First parameter must be const if (!PointeeType.isConstQualified() || PointeeType.isVolatileQualified()) { Diag((*Param)->getSourceRange().getBegin(), diag::err_literal_operator_param) << FirstParamType << "'const char *'" << (*Param)->getSourceRange(); return true; } QualType InnerType = PointeeType.getUnqualifiedType(); // Only const char *, const wchar_t*, const char16_t*, and const char32_t* // are allowed as the first parameter to a two-parameter function if (!(Context.hasSameType(InnerType, Context.CharTy) || Context.hasSameType(InnerType, Context.WideCharTy) || Context.hasSameType(InnerType, Context.Char16Ty) || Context.hasSameType(InnerType, Context.Char32Ty))) { Diag((*Param)->getSourceRange().getBegin(), diag::err_literal_operator_param) << FirstParamType << "'const char *'" << (*Param)->getSourceRange(); return true; } // Move on to the second and final parameter. ++Param; // The second parameter must be a std::size_t. QualType SecondParamType = (*Param)->getType().getUnqualifiedType(); if (!Context.hasSameType(SecondParamType, Context.getSizeType())) { Diag((*Param)->getSourceRange().getBegin(), diag::err_literal_operator_param) << SecondParamType << Context.getSizeType() << (*Param)->getSourceRange(); return true; } } else { Diag(FnDecl->getLocation(), diag::err_literal_operator_bad_param_count); return true; } // Parameters are good. // A parameter-declaration-clause containing a default argument is not // equivalent to any of the permitted forms. for (auto Param : FnDecl->parameters()) { if (Param->hasDefaultArg()) { Diag(Param->getDefaultArgRange().getBegin(), diag::err_literal_operator_default_argument) << Param->getDefaultArgRange(); break; } } StringRef LiteralName = FnDecl->getDeclName().getCXXLiteralIdentifier()->getName(); if (LiteralName[0] != '_' && !getSourceManager().isInSystemHeader(FnDecl->getLocation())) { // C++11 [usrlit.suffix]p1: // Literal suffix identifiers that do not start with an underscore // are reserved for future standardization. Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved) << StringLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName); } return false; } /// ActOnStartLinkageSpecification - Parsed the beginning of a C++ /// linkage specification, including the language and (if present) /// the '{'. ExternLoc is the location of the 'extern', Lang is the /// language string literal. LBraceLoc, if valid, provides the location of /// the '{' brace. Otherwise, this linkage specification does not /// have any braces. Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, Expr *LangStr, SourceLocation LBraceLoc) { StringLiteral *Lit = cast(LangStr); if (!Lit->isAscii()) { Diag(LangStr->getExprLoc(), diag::err_language_linkage_spec_not_ascii) << LangStr->getSourceRange(); return nullptr; } StringRef Lang = Lit->getString(); LinkageSpecDecl::LanguageIDs Language; if (Lang == "C") Language = LinkageSpecDecl::lang_c; else if (Lang == "C++") Language = LinkageSpecDecl::lang_cxx; else { Diag(LangStr->getExprLoc(), diag::err_language_linkage_spec_unknown) << LangStr->getSourceRange(); return nullptr; } // FIXME: Add all the various semantics of linkage specifications LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext, ExternLoc, LangStr->getExprLoc(), Language, LBraceLoc.isValid()); CurContext->addDecl(D); PushDeclContext(S, D); return D; } /// ActOnFinishLinkageSpecification - Complete the definition of /// the C++ linkage specification LinkageSpec. If RBraceLoc is /// valid, it's the position of the closing '}' brace in a linkage /// specification that uses braces. Decl *Sema::ActOnFinishLinkageSpecification(Scope *S, Decl *LinkageSpec, SourceLocation RBraceLoc) { if (RBraceLoc.isValid()) { LinkageSpecDecl* LSDecl = cast(LinkageSpec); LSDecl->setRBraceLoc(RBraceLoc); } PopDeclContext(); return LinkageSpec; } Decl *Sema::ActOnEmptyDeclaration(Scope *S, AttributeList *AttrList, SourceLocation SemiLoc) { Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc); // Attribute declarations appertain to empty declaration so we handle // them here. if (AttrList) ProcessDeclAttributeList(S, ED, AttrList); CurContext->addDecl(ED); return ED; } /// \brief Perform semantic analysis for the variable declaration that /// occurs within a C++ catch clause, returning the newly-created /// variable. VarDecl *Sema::BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo, SourceLocation StartLoc, SourceLocation Loc, IdentifierInfo *Name) { bool Invalid = false; QualType ExDeclType = TInfo->getType(); // Arrays and functions decay. if (ExDeclType->isArrayType()) ExDeclType = Context.getArrayDecayedType(ExDeclType); else if (ExDeclType->isFunctionType()) ExDeclType = Context.getPointerType(ExDeclType); // C++ 15.3p1: The exception-declaration shall not denote an incomplete type. // The exception-declaration shall not denote a pointer or reference to an // incomplete type, other than [cv] void*. // N2844 forbids rvalue references. if (!ExDeclType->isDependentType() && ExDeclType->isRValueReferenceType()) { Diag(Loc, diag::err_catch_rvalue_ref); Invalid = true; } if (ExDeclType->isVariablyModifiedType()) { Diag(Loc, diag::err_catch_variably_modified) << ExDeclType; Invalid = true; } QualType BaseType = ExDeclType; int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference unsigned DK = diag::err_catch_incomplete; if (const PointerType *Ptr = BaseType->getAs()) { BaseType = Ptr->getPointeeType(); Mode = 1; DK = diag::err_catch_incomplete_ptr; } else if (const ReferenceType *Ref = BaseType->getAs()) { // For the purpose of error recovery, we treat rvalue refs like lvalue refs. BaseType = Ref->getPointeeType(); Mode = 2; DK = diag::err_catch_incomplete_ref; } if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) && !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK)) Invalid = true; if (!Invalid && !ExDeclType->isDependentType() && RequireNonAbstractType(Loc, ExDeclType, diag::err_abstract_type_in_decl, AbstractVariableType)) Invalid = true; // Only the non-fragile NeXT runtime currently supports C++ catches // of ObjC types, and no runtime supports catching ObjC types by value. if (!Invalid && getLangOpts().ObjC1) { QualType T = ExDeclType; if (const ReferenceType *RT = T->getAs()) T = RT->getPointeeType(); if (T->isObjCObjectType()) { Diag(Loc, diag::err_objc_object_catch); Invalid = true; } else if (T->isObjCObjectPointerType()) { // FIXME: should this be a test for macosx-fragile specifically? if (getLangOpts().ObjCRuntime.isFragile()) Diag(Loc, diag::warn_objc_pointer_cxx_catch_fragile); } } VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name, ExDeclType, TInfo, SC_None); ExDecl->setExceptionVariable(true); // In ARC, infer 'retaining' for variables of retainable type. if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(ExDecl)) Invalid = true; if (!Invalid && !ExDeclType->isDependentType()) { if (const RecordType *recordType = ExDeclType->getAs()) { // Insulate this from anything else we might currently be parsing. EnterExpressionEvaluationContext scope( *this, ExpressionEvaluationContext::PotentiallyEvaluated); // C++ [except.handle]p16: // The object declared in an exception-declaration or, if the // exception-declaration does not specify a name, a temporary (12.2) is // copy-initialized (8.5) from the exception object. [...] // The object is destroyed when the handler exits, after the destruction // of any automatic objects initialized within the handler. // // We just pretend to initialize the object with itself, then make sure // it can be destroyed later. QualType initType = Context.getExceptionObjectType(ExDeclType); InitializedEntity entity = InitializedEntity::InitializeVariable(ExDecl); InitializationKind initKind = InitializationKind::CreateCopy(Loc, SourceLocation()); Expr *opaqueValue = new (Context) OpaqueValueExpr(Loc, initType, VK_LValue, OK_Ordinary); InitializationSequence sequence(*this, entity, initKind, opaqueValue); ExprResult result = sequence.Perform(*this, entity, initKind, opaqueValue); if (result.isInvalid()) Invalid = true; else { // If the constructor used was non-trivial, set this as the // "initializer". CXXConstructExpr *construct = result.getAs(); if (!construct->getConstructor()->isTrivial()) { Expr *init = MaybeCreateExprWithCleanups(construct); ExDecl->setInit(init); } // And make sure it's destructable. FinalizeVarWithDestructor(ExDecl, recordType); } } } if (Invalid) ExDecl->setInvalidDecl(); return ExDecl; } /// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch /// handler. Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); bool Invalid = D.isInvalidType(); // Check for unexpanded parameter packs. if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, UPPC_ExceptionType)) { TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy, D.getIdentifierLoc()); Invalid = true; } IdentifierInfo *II = D.getIdentifier(); if (NamedDecl *PrevDecl = LookupSingleName(S, II, D.getIdentifierLoc(), LookupOrdinaryName, ForRedeclaration)) { // The scope should be freshly made just for us. There is just no way // it contains any previous declaration, except for function parameters in // a function-try-block's catch statement. assert(!S->isDeclScope(PrevDecl)); if (isDeclInScope(PrevDecl, CurContext, S)) { Diag(D.getIdentifierLoc(), diag::err_redefinition) << D.getIdentifier(); Diag(PrevDecl->getLocation(), diag::note_previous_definition); Invalid = true; } else if (PrevDecl->isTemplateParameter()) // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); } if (D.getCXXScopeSpec().isSet() && !Invalid) { Diag(D.getIdentifierLoc(), diag::err_qualified_catch_declarator) << D.getCXXScopeSpec().getRange(); Invalid = true; } VarDecl *ExDecl = BuildExceptionDeclaration(S, TInfo, D.getLocStart(), D.getIdentifierLoc(), D.getIdentifier()); if (Invalid) ExDecl->setInvalidDecl(); // Add the exception declaration into this scope. if (II) PushOnScopeChains(ExDecl, S); else CurContext->addDecl(ExDecl); ProcessDeclAttributes(S, ExDecl, D); return ExDecl; } Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, Expr *AssertExpr, Expr *AssertMessageExpr, SourceLocation RParenLoc) { StringLiteral *AssertMessage = AssertMessageExpr ? cast(AssertMessageExpr) : nullptr; if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression)) return nullptr; return BuildStaticAssertDeclaration(StaticAssertLoc, AssertExpr, AssertMessage, RParenLoc, false); } Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, Expr *AssertExpr, StringLiteral *AssertMessage, SourceLocation RParenLoc, bool Failed) { assert(AssertExpr != nullptr && "Expected non-null condition"); if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent() && !Failed) { // In a static_assert-declaration, the constant-expression shall be a // constant expression that can be contextually converted to bool. ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr); if (Converted.isInvalid()) Failed = true; llvm::APSInt Cond; if (!Failed && VerifyIntegerConstantExpression(Converted.get(), &Cond, diag::err_static_assert_expression_is_not_constant, /*AllowFold=*/false).isInvalid()) Failed = true; if (!Failed && !Cond) { SmallString<256> MsgBuffer; llvm::raw_svector_ostream Msg(MsgBuffer); if (AssertMessage) AssertMessage->printPretty(Msg, nullptr, getPrintingPolicy()); Diag(StaticAssertLoc, diag::err_static_assert_failed) << !AssertMessage << Msg.str() << AssertExpr->getSourceRange(); Failed = true; } } ExprResult FullAssertExpr = ActOnFinishFullExpr(AssertExpr, StaticAssertLoc, /*DiscardedValue*/false, /*IsConstexpr*/true); if (FullAssertExpr.isInvalid()) Failed = true; else AssertExpr = FullAssertExpr.get(); Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc, AssertExpr, AssertMessage, RParenLoc, Failed); CurContext->addDecl(Decl); return Decl; } /// \brief Perform semantic analysis of the given friend type declaration. /// /// \returns A friend declaration that. FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart, SourceLocation FriendLoc, TypeSourceInfo *TSInfo) { assert(TSInfo && "NULL TypeSourceInfo for friend type declaration"); QualType T = TSInfo->getType(); SourceRange TypeRange = TSInfo->getTypeLoc().getLocalSourceRange(); // C++03 [class.friend]p2: // An elaborated-type-specifier shall be used in a friend declaration // for a class.* // // * The class-key of the elaborated-type-specifier is required. if (!CodeSynthesisContexts.empty()) { // Do not complain about the form of friend template types during any kind // of code synthesis. For template instantiation, we will have complained // when the template was defined. } else { if (!T->isElaboratedTypeSpecifier()) { // If we evaluated the type to a record type, suggest putting // a tag in front. if (const RecordType *RT = T->getAs()) { RecordDecl *RD = RT->getDecl(); SmallString<16> InsertionText(" "); InsertionText += RD->getKindName(); Diag(TypeRange.getBegin(), getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_unelaborated_friend_type : diag::ext_unelaborated_friend_type) << (unsigned) RD->getTagKind() << T << FixItHint::CreateInsertion(getLocForEndOfToken(FriendLoc), InsertionText); } else { Diag(FriendLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_nonclass_type_friend : diag::ext_nonclass_type_friend) << T << TypeRange; } } else if (T->getAs()) { Diag(FriendLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_enum_friend : diag::ext_enum_friend) << T << TypeRange; } // C++11 [class.friend]p3: // A friend declaration that does not declare a function shall have one // of the following forms: // friend elaborated-type-specifier ; // friend simple-type-specifier ; // friend typename-specifier ; if (getLangOpts().CPlusPlus11 && LocStart != FriendLoc) Diag(FriendLoc, diag::err_friend_not_first_in_declaration) << T; } // If the type specifier in a friend declaration designates a (possibly // cv-qualified) class type, that class is declared as a friend; otherwise, // the friend declaration is ignored. return FriendDecl::Create(Context, CurContext, TSInfo->getTypeLoc().getLocStart(), TSInfo, FriendLoc); } /// Handle a friend tag declaration where the scope specifier was /// templated. Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, MultiTemplateParamsArg TempParamLists) { TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); bool IsMemberSpecialization = false; bool Invalid = false; if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( TagLoc, NameLoc, SS, nullptr, TempParamLists, /*friend*/ true, IsMemberSpecialization, Invalid)) { if (TemplateParams->size() > 0) { // This is a declaration of a class template. if (Invalid) return nullptr; return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, Attr, TemplateParams, AS_public, /*ModulePrivateLoc=*/SourceLocation(), FriendLoc, TempParamLists.size() - 1, TempParamLists.data()).get(); } else { // The "template<>" header is extraneous. Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams) << TypeWithKeyword::getTagTypeKindName(Kind) << Name; IsMemberSpecialization = true; } } if (Invalid) return nullptr; bool isAllExplicitSpecializations = true; for (unsigned I = TempParamLists.size(); I-- > 0; ) { if (TempParamLists[I]->size()) { isAllExplicitSpecializations = false; break; } } // FIXME: don't ignore attributes. // If it's explicit specializations all the way down, just forget // about the template header and build an appropriate non-templated // friend. TODO: for source fidelity, remember the headers. if (isAllExplicitSpecializations) { if (SS.isEmpty()) { bool Owned = false; bool IsDependent = false; return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, Attr, AS_public, /*ModulePrivateLoc=*/SourceLocation(), MultiTemplateParamsArg(), Owned, IsDependent, /*ScopedEnumKWLoc=*/SourceLocation(), /*ScopedEnumUsesClassTag=*/false, /*UnderlyingType=*/TypeResult(), /*IsTypeSpecifier=*/false, /*IsTemplateParamOrArg=*/false); } NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); ElaboratedTypeKeyword Keyword = TypeWithKeyword::getKeywordForTagTypeKind(Kind); QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc, *Name, NameLoc); if (T.isNull()) return nullptr; TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); if (isa(T)) { DependentNameTypeLoc TL = TSI->getTypeLoc().castAs(); TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(QualifierLoc); TL.setNameLoc(NameLoc); } else { ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs(); TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(QualifierLoc); TL.getNamedTypeLoc().castAs().setNameLoc(NameLoc); } FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, TSI, FriendLoc, TempParamLists); Friend->setAccess(AS_public); CurContext->addDecl(Friend); return Friend; } assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?"); // Handle the case of a templated-scope friend class. e.g. // template class A::B; // FIXME: we don't support these right now. Diag(NameLoc, diag::warn_template_qualified_friend_unsupported) << SS.getScopeRep() << SS.getRange() << cast(CurContext); ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind); QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name); TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); DependentNameTypeLoc TL = TSI->getTypeLoc().castAs(); TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(SS.getWithLocInContext(Context)); TL.setNameLoc(NameLoc); FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, TSI, FriendLoc, TempParamLists); Friend->setAccess(AS_public); Friend->setUnsupportedFriend(true); CurContext->addDecl(Friend); return Friend; } /// Handle a friend type declaration. This works in tandem with /// ActOnTag. /// /// Notes on friend class templates: /// /// We generally treat friend class declarations as if they were /// declaring a class. So, for example, the elaborated type specifier /// in a friend declaration is required to obey the restrictions of a /// class-head (i.e. no typedefs in the scope chain), template /// parameters are required to match up with simple template-ids, &c. /// However, unlike when declaring a template specialization, it's /// okay to refer to a template specialization without an empty /// template parameter declaration, e.g. /// friend class A::B; /// We permit this as a special case; if there are any template /// parameters present at all, require proper matching, i.e. /// template <> template \ friend class A::B; Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, MultiTemplateParamsArg TempParams) { SourceLocation Loc = DS.getLocStart(); assert(DS.isFriendSpecified()); assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified); // Try to convert the decl specifier to a type. This works for // friend templates because ActOnTag never produces a ClassTemplateDecl // for a TUK_Friend. Declarator TheDeclarator(DS, Declarator::MemberContext); TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S); QualType T = TSI->getType(); if (TheDeclarator.isInvalidType()) return nullptr; if (DiagnoseUnexpandedParameterPack(Loc, TSI, UPPC_FriendDeclaration)) return nullptr; // This is definitely an error in C++98. It's probably meant to // be forbidden in C++0x, too, but the specification is just // poorly written. // // The problem is with declarations like the following: // template friend A::foo; // where deciding whether a class C is a friend or not now hinges // on whether there exists an instantiation of A that causes // 'foo' to equal C. There are restrictions on class-heads // (which we declare (by fiat) elaborated friend declarations to // be) that makes this tractable. // // FIXME: handle "template <> friend class A;", which // is possibly well-formed? Who even knows? if (TempParams.size() && !T->isElaboratedTypeSpecifier()) { Diag(Loc, diag::err_tagless_friend_type_template) << DS.getSourceRange(); return nullptr; } // C++98 [class.friend]p1: A friend of a class is a function // or class that is not a member of the class . . . // This is fixed in DR77, which just barely didn't make the C++03 // deadline. It's also a very silly restriction that seriously // affects inner classes and which nobody else seems to implement; // thus we never diagnose it, not even in -pedantic. // // But note that we could warn about it: it's always useless to // friend one of your own members (it's not, however, worthless to // friend a member of an arbitrary specialization of your template). Decl *D; if (!TempParams.empty()) D = FriendTemplateDecl::Create(Context, CurContext, Loc, TempParams, TSI, DS.getFriendSpecLoc()); else D = CheckFriendTypeDecl(Loc, DS.getFriendSpecLoc(), TSI); if (!D) return nullptr; D->setAccess(AS_public); CurContext->addDecl(D); return D; } NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParams) { const DeclSpec &DS = D.getDeclSpec(); assert(DS.isFriendSpecified()); assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified); SourceLocation Loc = D.getIdentifierLoc(); TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); // C++ [class.friend]p1 // A friend of a class is a function or class.... // Note that this sees through typedefs, which is intended. // It *doesn't* see through dependent types, which is correct // according to [temp.arg.type]p3: // If a declaration acquires a function type through a // type dependent on a template-parameter and this causes // a declaration that does not use the syntactic form of a // function declarator to have a function type, the program // is ill-formed. if (!TInfo->getType()->isFunctionType()) { Diag(Loc, diag::err_unexpected_friend); // It might be worthwhile to try to recover by creating an // appropriate declaration. return nullptr; } // C++ [namespace.memdef]p3 // - If a friend declaration in a non-local class first declares a // class or function, the friend class or function is a member // of the innermost enclosing namespace. // - The name of the friend is not found by simple name lookup // until a matching declaration is provided in that namespace // scope (either before or after the class declaration granting // friendship). // - If a friend function is called, its name may be found by the // name lookup that considers functions from namespaces and // classes associated with the types of the function arguments. // - When looking for a prior declaration of a class or a function // declared as a friend, scopes outside the innermost enclosing // namespace scope are not considered. CXXScopeSpec &SS = D.getCXXScopeSpec(); DeclarationNameInfo NameInfo = GetNameForDeclarator(D); DeclarationName Name = NameInfo.getName(); assert(Name); // Check for unexpanded parameter packs. if (DiagnoseUnexpandedParameterPack(Loc, TInfo, UPPC_FriendDeclaration) || DiagnoseUnexpandedParameterPack(NameInfo, UPPC_FriendDeclaration) || DiagnoseUnexpandedParameterPack(SS, UPPC_FriendDeclaration)) return nullptr; // The context we found the declaration in, or in which we should // create the declaration. DeclContext *DC; Scope *DCScope = S; LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); // There are five cases here. // - There's no scope specifier and we're in a local class. Only look // for functions declared in the immediately-enclosing block scope. // We recover from invalid scope qualifiers as if they just weren't there. FunctionDecl *FunctionContainingLocalClass = nullptr; if ((SS.isInvalid() || !SS.isSet()) && (FunctionContainingLocalClass = cast(CurContext)->isLocalClass())) { // C++11 [class.friend]p11: // If a friend declaration appears in a local class and the name // specified is an unqualified name, a prior declaration is // looked up without considering scopes that are outside the // innermost enclosing non-class scope. For a friend function // declaration, if there is no prior declaration, the program is // ill-formed. // Find the innermost enclosing non-class scope. This is the block // scope containing the local class definition (or for a nested class, // the outer local class). DCScope = S->getFnParent(); // Look up the function name in the scope. Previous.clear(LookupLocalFriendName); LookupName(Previous, S, /*AllowBuiltinCreation*/false); if (!Previous.empty()) { // All possible previous declarations must have the same context: // either they were declared at block scope or they are members of // one of the enclosing local classes. DC = Previous.getRepresentativeDecl()->getDeclContext(); } else { // This is ill-formed, but provide the context that we would have // declared the function in, if we were permitted to, for error recovery. DC = FunctionContainingLocalClass; } adjustContextForLocalExternDecl(DC); // C++ [class.friend]p6: // A function can be defined in a friend declaration of a class if and // only if the class is a non-local class (9.8), the function name is // unqualified, and the function has namespace scope. if (D.isFunctionDefinition()) { Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class); } // - There's no scope specifier, in which case we just go to the // appropriate scope and look for a function or function template // there as appropriate. } else if (SS.isInvalid() || !SS.isSet()) { // C++11 [namespace.memdef]p3: // If the name in a friend declaration is neither qualified nor // a template-id and the declaration is a function or an // elaborated-type-specifier, the lookup to determine whether // the entity has been previously declared shall not consider // any scopes outside the innermost enclosing namespace. bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId; // Find the appropriate context according to the above. DC = CurContext; // Skip class contexts. If someone can cite chapter and verse // for this behavior, that would be nice --- it's what GCC and // EDG do, and it seems like a reasonable intent, but the spec // really only says that checks for unqualified existing // declarations should stop at the nearest enclosing namespace, // not that they should only consider the nearest enclosing // namespace. while (DC->isRecord()) DC = DC->getParent(); DeclContext *LookupDC = DC; while (LookupDC->isTransparentContext()) LookupDC = LookupDC->getParent(); while (true) { LookupQualifiedName(Previous, LookupDC); if (!Previous.empty()) { DC = LookupDC; break; } if (isTemplateId) { if (isa(LookupDC)) break; } else { if (LookupDC->isFileContext()) break; } LookupDC = LookupDC->getParent(); } DCScope = getScopeForDeclContext(S, DC); // - There's a non-dependent scope specifier, in which case we // compute it and do a previous lookup there for a function // or function template. } else if (!SS.getScopeRep()->isDependent()) { DC = computeDeclContext(SS); if (!DC) return nullptr; if (RequireCompleteDeclContext(SS, DC)) return nullptr; LookupQualifiedName(Previous, DC); // Ignore things found implicitly in the wrong scope. // TODO: better diagnostics for this case. Suggesting the right // qualified scope would be nice... LookupResult::Filter F = Previous.makeFilter(); while (F.hasNext()) { NamedDecl *D = F.next(); if (!DC->InEnclosingNamespaceSetOf( D->getDeclContext()->getRedeclContext())) F.erase(); } F.done(); if (Previous.empty()) { D.setInvalidType(); Diag(Loc, diag::err_qualified_friend_not_found) << Name << TInfo->getType(); return nullptr; } // C++ [class.friend]p1: A friend of a class is a function or // class that is not a member of the class . . . if (DC->Equals(CurContext)) Diag(DS.getFriendSpecLoc(), getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_friend_is_member : diag::err_friend_is_member); if (D.isFunctionDefinition()) { // C++ [class.friend]p6: // A function can be defined in a friend declaration of a class if and // only if the class is a non-local class (9.8), the function name is // unqualified, and the function has namespace scope. SemaDiagnosticBuilder DB = Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def); DB << SS.getScopeRep(); if (DC->isFileContext()) DB << FixItHint::CreateRemoval(SS.getRange()); SS.clear(); } // - There's a scope specifier that does not match any template // parameter lists, in which case we use some arbitrary context, // create a method or method template, and wait for instantiation. // - There's a scope specifier that does match some template // parameter lists, which we don't handle right now. } else { if (D.isFunctionDefinition()) { // C++ [class.friend]p6: // A function can be defined in a friend declaration of a class if and // only if the class is a non-local class (9.8), the function name is // unqualified, and the function has namespace scope. Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def) << SS.getScopeRep(); } DC = CurContext; assert(isa(DC) && "friend declaration not in class?"); } if (!DC->isRecord()) { int DiagArg = -1; switch (D.getName().getKind()) { case UnqualifiedId::IK_ConstructorTemplateId: case UnqualifiedId::IK_ConstructorName: DiagArg = 0; break; case UnqualifiedId::IK_DestructorName: DiagArg = 1; break; case UnqualifiedId::IK_ConversionFunctionId: DiagArg = 2; break; case UnqualifiedId::IK_DeductionGuideName: DiagArg = 3; break; case UnqualifiedId::IK_Identifier: case UnqualifiedId::IK_ImplicitSelfParam: case UnqualifiedId::IK_LiteralOperatorId: case UnqualifiedId::IK_OperatorFunctionId: case UnqualifiedId::IK_TemplateId: break; } // This implies that it has to be an operator or function. if (DiagArg >= 0) { Diag(Loc, diag::err_introducing_special_friend) << DiagArg; return nullptr; } } // FIXME: This is an egregious hack to cope with cases where the scope stack // does not contain the declaration context, i.e., in an out-of-line // definition of a class. Scope FakeDCScope(S, Scope::DeclScope, Diags); if (!DCScope) { FakeDCScope.setEntity(DC); DCScope = &FakeDCScope; } bool AddToScope = true; NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous, TemplateParams, AddToScope); if (!ND) return nullptr; assert(ND->getLexicalDeclContext() == CurContext); // If we performed typo correction, we might have added a scope specifier // and changed the decl context. DC = ND->getDeclContext(); // Add the function declaration to the appropriate lookup tables, // adjusting the redeclarations list as necessary. We don't // want to do this yet if the friending class is dependent. // // Also update the scope-based lookup if the target context's // lookup context is in lexical scope. if (!CurContext->isDependentContext()) { DC = DC->getRedeclContext(); DC->makeDeclVisibleInContext(ND); if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false); } FriendDecl *FrD = FriendDecl::Create(Context, CurContext, D.getIdentifierLoc(), ND, DS.getFriendSpecLoc()); FrD->setAccess(AS_public); CurContext->addDecl(FrD); if (ND->isInvalidDecl()) { FrD->setInvalidDecl(); } else { if (DC->isRecord()) CheckFriendAccess(ND); FunctionDecl *FD; if (FunctionTemplateDecl *FTD = dyn_cast(ND)) FD = FTD->getTemplatedDecl(); else FD = cast(ND); // C++11 [dcl.fct.default]p4: If a friend declaration specifies a // default argument expression, that declaration shall be a definition // and shall be the only declaration of the function or function // template in the translation unit. if (functionDeclHasDefaultArgument(FD)) { // We can't look at FD->getPreviousDecl() because it may not have been set // if we're in a dependent context. If the function is known to be a // redeclaration, we will have narrowed Previous down to the right decl. if (D.isRedeclaration()) { Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_redeclared); Diag(Previous.getRepresentativeDecl()->getLocation(), diag::note_previous_declaration); } else if (!D.isFunctionDefinition()) Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_must_be_def); } // Mark templated-scope function declarations as unsupported. if (FD->getNumTemplateParameterLists() && SS.isValid()) { Diag(FD->getLocation(), diag::warn_template_qualified_friend_unsupported) << SS.getScopeRep() << SS.getRange() << cast(CurContext); FrD->setUnsupportedFriend(true); } } return ND; } void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { AdjustDeclIfTemplate(Dcl); FunctionDecl *Fn = dyn_cast_or_null(Dcl); if (!Fn) { Diag(DelLoc, diag::err_deleted_non_function); return; } // Deleted function does not have a body. Fn->setWillHaveBody(false); if (const FunctionDecl *Prev = Fn->getPreviousDecl()) { // Don't consider the implicit declaration we generate for explicit // specializations. FIXME: Do not generate these implicit declarations. if ((Prev->getTemplateSpecializationKind() != TSK_ExplicitSpecialization || Prev->getPreviousDecl()) && !Prev->isDefined()) { Diag(DelLoc, diag::err_deleted_decl_not_first); Diag(Prev->getLocation().isInvalid() ? DelLoc : Prev->getLocation(), Prev->isImplicit() ? diag::note_previous_implicit_declaration : diag::note_previous_declaration); } // If the declaration wasn't the first, we delete the function anyway for // recovery. Fn = Fn->getCanonicalDecl(); } // dllimport/dllexport cannot be deleted. if (const InheritableAttr *DLLAttr = getDLLAttr(Fn)) { Diag(Fn->getLocation(), diag::err_attribute_dll_deleted) << DLLAttr; Fn->setInvalidDecl(); } if (Fn->isDeleted()) return; // See if we're deleting a function which is already known to override a // non-deleted virtual function. if (CXXMethodDecl *MD = dyn_cast(Fn)) { bool IssuedDiagnostic = false; for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), E = MD->end_overridden_methods(); I != E; ++I) { if (!(*MD->begin_overridden_methods())->isDeleted()) { if (!IssuedDiagnostic) { Diag(DelLoc, diag::err_deleted_override) << MD->getDeclName(); IssuedDiagnostic = true; } Diag((*I)->getLocation(), diag::note_overridden_virtual_function); } } // If this function was implicitly deleted because it was defaulted, // explain why it was deleted. if (IssuedDiagnostic && MD->isDefaulted()) ShouldDeleteSpecialMember(MD, getSpecialMember(MD), nullptr, /*Diagnose*/true); } // C++11 [basic.start.main]p3: // A program that defines main as deleted [...] is ill-formed. if (Fn->isMain()) Diag(DelLoc, diag::err_deleted_main); // C++11 [dcl.fct.def.delete]p4: // A deleted function is implicitly inline. Fn->setImplicitlyInline(); Fn->setDeletedAsWritten(); } void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { CXXMethodDecl *MD = dyn_cast_or_null(Dcl); if (MD) { if (MD->getParent()->isDependentType()) { MD->setDefaulted(); MD->setExplicitlyDefaulted(); return; } CXXSpecialMember Member = getSpecialMember(MD); if (Member == CXXInvalid) { if (!MD->isInvalidDecl()) Diag(DefaultLoc, diag::err_default_special_members); return; } MD->setDefaulted(); MD->setExplicitlyDefaulted(); // Unset that we will have a body for this function. We might not, // if it turns out to be trivial, and we don't need this marking now // that we've marked it as defaulted. MD->setWillHaveBody(false); // If this definition appears within the record, do the checking when // the record is complete. const FunctionDecl *Primary = MD; if (const FunctionDecl *Pattern = MD->getTemplateInstantiationPattern()) // Ask the template instantiation pattern that actually had the // '= default' on it. Primary = Pattern; // If the method was defaulted on its first declaration, we will have // already performed the checking in CheckCompletedCXXClass. Such a // declaration doesn't trigger an implicit definition. if (Primary->getCanonicalDecl()->isDefaulted()) return; CheckExplicitlyDefaultedSpecialMember(MD); if (!MD->isInvalidDecl()) DefineImplicitSpecialMember(*this, MD, DefaultLoc); } else { Diag(DefaultLoc, diag::err_default_special_members); } } static void SearchForReturnInStmt(Sema &Self, Stmt *S) { for (Stmt *SubStmt : S->children()) { if (!SubStmt) continue; if (isa(SubStmt)) Self.Diag(SubStmt->getLocStart(), diag::err_return_in_constructor_handler); if (!isa(SubStmt)) SearchForReturnInStmt(Self, SubStmt); } } void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) { for (unsigned I = 0, E = TryBlock->getNumHandlers(); I != E; ++I) { CXXCatchStmt *Handler = TryBlock->getHandler(I); SearchForReturnInStmt(*this, Handler); } } bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New, const CXXMethodDecl *Old) { const FunctionType *NewFT = New->getType()->getAs(); const FunctionType *OldFT = Old->getType()->getAs(); CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv(); // If the calling conventions match, everything is fine if (NewCC == OldCC) return false; // If the calling conventions mismatch because the new function is static, // suppress the calling convention mismatch error; the error about static // function override (err_static_overrides_virtual from // Sema::CheckFunctionDeclaration) is more clear. if (New->getStorageClass() == SC_Static) return false; Diag(New->getLocation(), diag::err_conflicting_overriding_cc_attributes) << New->getDeclName() << New->getType() << Old->getType(); Diag(Old->getLocation(), diag::note_overridden_virtual_function); return true; } bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, const CXXMethodDecl *Old) { QualType NewTy = New->getType()->getAs()->getReturnType(); QualType OldTy = Old->getType()->getAs()->getReturnType(); if (Context.hasSameType(NewTy, OldTy) || NewTy->isDependentType() || OldTy->isDependentType()) return false; // Check if the return types are covariant QualType NewClassTy, OldClassTy; /// Both types must be pointers or references to classes. if (const PointerType *NewPT = NewTy->getAs()) { if (const PointerType *OldPT = OldTy->getAs()) { NewClassTy = NewPT->getPointeeType(); OldClassTy = OldPT->getPointeeType(); } } else if (const ReferenceType *NewRT = NewTy->getAs()) { if (const ReferenceType *OldRT = OldTy->getAs()) { if (NewRT->getTypeClass() == OldRT->getTypeClass()) { NewClassTy = NewRT->getPointeeType(); OldClassTy = OldRT->getPointeeType(); } } } // The return types aren't either both pointers or references to a class type. if (NewClassTy.isNull()) { Diag(New->getLocation(), diag::err_different_return_type_for_overriding_virtual_function) << New->getDeclName() << NewTy << OldTy << New->getReturnTypeSourceRange(); Diag(Old->getLocation(), diag::note_overridden_virtual_function) << Old->getReturnTypeSourceRange(); return true; } if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) { // C++14 [class.virtual]p8: // If the class type in the covariant return type of D::f differs from // that of B::f, the class type in the return type of D::f shall be // complete at the point of declaration of D::f or shall be the class // type D. if (const RecordType *RT = NewClassTy->getAs()) { if (!RT->isBeingDefined() && RequireCompleteType(New->getLocation(), NewClassTy, diag::err_covariant_return_incomplete, New->getDeclName())) return true; } // Check if the new class derives from the old class. if (!IsDerivedFrom(New->getLocation(), NewClassTy, OldClassTy)) { Diag(New->getLocation(), diag::err_covariant_return_not_derived) << New->getDeclName() << NewTy << OldTy << New->getReturnTypeSourceRange(); Diag(Old->getLocation(), diag::note_overridden_virtual_function) << Old->getReturnTypeSourceRange(); return true; } // Check if we the conversion from derived to base is valid. if (CheckDerivedToBaseConversion( NewClassTy, OldClassTy, diag::err_covariant_return_inaccessible_base, diag::err_covariant_return_ambiguous_derived_to_base_conv, New->getLocation(), New->getReturnTypeSourceRange(), New->getDeclName(), nullptr)) { // FIXME: this note won't trigger for delayed access control // diagnostics, and it's impossible to get an undelayed error // here from access control during the original parse because // the ParsingDeclSpec/ParsingDeclarator are still in scope. Diag(Old->getLocation(), diag::note_overridden_virtual_function) << Old->getReturnTypeSourceRange(); return true; } } // The qualifiers of the return types must be the same. if (NewTy.getLocalCVRQualifiers() != OldTy.getLocalCVRQualifiers()) { Diag(New->getLocation(), diag::err_covariant_return_type_different_qualifications) << New->getDeclName() << NewTy << OldTy << New->getReturnTypeSourceRange(); Diag(Old->getLocation(), diag::note_overridden_virtual_function) << Old->getReturnTypeSourceRange(); return true; } // The new class type must have the same or less qualifiers as the old type. if (NewClassTy.isMoreQualifiedThan(OldClassTy)) { Diag(New->getLocation(), diag::err_covariant_return_type_class_type_more_qualified) << New->getDeclName() << NewTy << OldTy << New->getReturnTypeSourceRange(); Diag(Old->getLocation(), diag::note_overridden_virtual_function) << Old->getReturnTypeSourceRange(); return true; } return false; } /// \brief Mark the given method pure. /// /// \param Method the method to be marked pure. /// /// \param InitRange the source range that covers the "0" initializer. bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) { SourceLocation EndLoc = InitRange.getEnd(); if (EndLoc.isValid()) Method->setRangeEnd(EndLoc); if (Method->isVirtual() || Method->getParent()->isDependentContext()) { Method->setPure(); return false; } if (!Method->isInvalidDecl()) Diag(Method->getLocation(), diag::err_non_virtual_pure) << Method->getDeclName() << InitRange; return true; } void Sema::ActOnPureSpecifier(Decl *D, SourceLocation ZeroLoc) { if (D->getFriendObjectKind()) Diag(D->getLocation(), diag::err_pure_friend); else if (auto *M = dyn_cast(D)) CheckPureMethod(M, ZeroLoc); else Diag(D->getLocation(), diag::err_illegal_initializer); } /// \brief Determine whether the given declaration is a static data member. static bool isStaticDataMember(const Decl *D) { if (const VarDecl *Var = dyn_cast_or_null(D)) return Var->isStaticDataMember(); return false; } /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse /// an initializer for the out-of-line declaration 'Dcl'. The scope /// is a fresh scope pushed for just this purpose. /// /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a /// static data member of class X, names should be looked up in the scope of /// class X. void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) { // If there is no declaration, there was an error parsing it. if (!D || D->isInvalidDecl()) return; // We will always have a nested name specifier here, but this declaration // might not be out of line if the specifier names the current namespace: // extern int n; // int ::n = 0; if (D->isOutOfLine()) EnterDeclaratorContext(S, D->getDeclContext()); // If we are parsing the initializer for a static data member, push a // new expression evaluation context that is associated with this static // data member. if (isStaticDataMember(D)) PushExpressionEvaluationContext( ExpressionEvaluationContext::PotentiallyEvaluated, D); } /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an /// initializer for the out-of-line declaration 'D'. void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) { // If there is no declaration, there was an error parsing it. if (!D || D->isInvalidDecl()) return; if (isStaticDataMember(D)) PopExpressionEvaluationContext(); if (D->isOutOfLine()) ExitDeclaratorContext(S); } /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a /// C++ if/switch/while/for statement. /// e.g: "if (int x = f()) {...}" DeclResult Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { // C++ 6.4p2: // The declarator shall not specify a function or an array. // The type-specifier-seq shall not contain typedef and shall not declare a // new class or enumeration. assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && "Parser allowed 'typedef' as storage class of condition decl."); Decl *Dcl = ActOnDeclarator(S, D); if (!Dcl) return true; if (isa(Dcl)) { // The declarator shall not specify a function. Diag(Dcl->getLocation(), diag::err_invalid_use_of_function_type) << D.getSourceRange(); return true; } return Dcl; } void Sema::LoadExternalVTableUses() { if (!ExternalSource) return; SmallVector VTables; ExternalSource->ReadUsedVTables(VTables); SmallVector NewUses; for (unsigned I = 0, N = VTables.size(); I != N; ++I) { llvm::DenseMap::iterator Pos = VTablesUsed.find(VTables[I].Record); // Even if a definition wasn't required before, it may be required now. if (Pos != VTablesUsed.end()) { if (!Pos->second && VTables[I].DefinitionRequired) Pos->second = true; continue; } VTablesUsed[VTables[I].Record] = VTables[I].DefinitionRequired; NewUses.push_back(VTableUse(VTables[I].Record, VTables[I].Location)); } VTableUses.insert(VTableUses.begin(), NewUses.begin(), NewUses.end()); } void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, bool DefinitionRequired) { // Ignore any vtable uses in unevaluated operands or for classes that do // not have a vtable. if (!Class->isDynamicClass() || Class->isDependentContext() || CurContext->isDependentContext() || isUnevaluatedContext()) return; // Try to insert this class into the map. LoadExternalVTableUses(); Class = cast(Class->getCanonicalDecl()); std::pair::iterator, bool> Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired)); if (!Pos.second) { // If we already had an entry, check to see if we are promoting this vtable // to require a definition. If so, we need to reappend to the VTableUses // list, since we may have already processed the first entry. if (DefinitionRequired && !Pos.first->second) { Pos.first->second = true; } else { // Otherwise, we can early exit. return; } } else { // The Microsoft ABI requires that we perform the destructor body // checks (i.e. operator delete() lookup) when the vtable is marked used, as // the deleting destructor is emitted with the vtable, not with the // destructor definition as in the Itanium ABI. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { CXXDestructorDecl *DD = Class->getDestructor(); if (DD && DD->isVirtual() && !DD->isDeleted()) { if (Class->hasUserDeclaredDestructor() && !DD->isDefined()) { // If this is an out-of-line declaration, marking it referenced will // not do anything. Manually call CheckDestructor to look up operator // delete(). ContextRAII SavedContext(*this, DD); CheckDestructor(DD); } else { MarkFunctionReferenced(Loc, Class->getDestructor()); } } } } // Local classes need to have their virtual members marked // immediately. For all other classes, we mark their virtual members // at the end of the translation unit. if (Class->isLocalClass()) MarkVirtualMembersReferenced(Loc, Class); else VTableUses.push_back(std::make_pair(Class, Loc)); } bool Sema::DefineUsedVTables() { LoadExternalVTableUses(); if (VTableUses.empty()) return false; // Note: The VTableUses vector could grow as a result of marking // the members of a class as "used", so we check the size each // time through the loop and prefer indices (which are stable) to // iterators (which are not). bool DefinedAnything = false; for (unsigned I = 0; I != VTableUses.size(); ++I) { CXXRecordDecl *Class = VTableUses[I].first->getDefinition(); if (!Class) continue; TemplateSpecializationKind ClassTSK = Class->getTemplateSpecializationKind(); SourceLocation Loc = VTableUses[I].second; bool DefineVTable = true; // If this class has a key function, but that key function is // defined in another translation unit, we don't need to emit the // vtable even though we're using it. const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(Class); if (KeyFunction && !KeyFunction->hasBody()) { // The key function is in another translation unit. DefineVTable = false; TemplateSpecializationKind TSK = KeyFunction->getTemplateSpecializationKind(); assert(TSK != TSK_ExplicitInstantiationDefinition && TSK != TSK_ImplicitInstantiation && "Instantiations don't have key functions"); (void)TSK; } else if (!KeyFunction) { // If we have a class with no key function that is the subject // of an explicit instantiation declaration, suppress the // vtable; it will live with the explicit instantiation // definition. bool IsExplicitInstantiationDeclaration = ClassTSK == TSK_ExplicitInstantiationDeclaration; for (auto R : Class->redecls()) { TemplateSpecializationKind TSK = cast(R)->getTemplateSpecializationKind(); if (TSK == TSK_ExplicitInstantiationDeclaration) IsExplicitInstantiationDeclaration = true; else if (TSK == TSK_ExplicitInstantiationDefinition) { IsExplicitInstantiationDeclaration = false; break; } } if (IsExplicitInstantiationDeclaration) DefineVTable = false; } // The exception specifications for all virtual members may be needed even // if we are not providing an authoritative form of the vtable in this TU. // We may choose to emit it available_externally anyway. if (!DefineVTable) { MarkVirtualMemberExceptionSpecsNeeded(Loc, Class); continue; } // Mark all of the virtual members of this class as referenced, so // that we can build a vtable. Then, tell the AST consumer that a // vtable for this class is required. DefinedAnything = true; MarkVirtualMembersReferenced(Loc, Class); CXXRecordDecl *Canonical = cast(Class->getCanonicalDecl()); if (VTablesUsed[Canonical]) Consumer.HandleVTable(Class); // Warn if we're emitting a weak vtable. The vtable will be weak if there is // no key function or the key function is inlined. Don't warn in C++ ABIs // that lack key functions, since the user won't be able to make one. if (Context.getTargetInfo().getCXXABI().hasKeyFunctions() && Class->isExternallyVisible() && ClassTSK != TSK_ImplicitInstantiation) { const FunctionDecl *KeyFunctionDef = nullptr; if (!KeyFunction || (KeyFunction->hasBody(KeyFunctionDef) && KeyFunctionDef->isInlined())) { Diag(Class->getLocation(), ClassTSK == TSK_ExplicitInstantiationDefinition ? diag::warn_weak_template_vtable : diag::warn_weak_vtable) << Class; } } } VTableUses.clear(); return DefinedAnything; } void Sema::MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc, const CXXRecordDecl *RD) { for (const auto *I : RD->methods()) if (I->isVirtual() && !I->isPure()) ResolveExceptionSpec(Loc, I->getType()->castAs()); } void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, const CXXRecordDecl *RD) { // Mark all functions which will appear in RD's vtable as used. CXXFinalOverriderMap FinalOverriders; RD->getFinalOverriders(FinalOverriders); for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(), E = FinalOverriders.end(); I != E; ++I) { for (OverridingMethods::const_iterator OI = I->second.begin(), OE = I->second.end(); OI != OE; ++OI) { assert(OI->second.size() > 0 && "no final overrider"); CXXMethodDecl *Overrider = OI->second.front().Method; // C++ [basic.def.odr]p2: // [...] A virtual member function is used if it is not pure. [...] if (!Overrider->isPure()) MarkFunctionReferenced(Loc, Overrider); } } // Only classes that have virtual bases need a VTT. if (RD->getNumVBases() == 0) return; for (const auto &I : RD->bases()) { const CXXRecordDecl *Base = cast(I.getType()->getAs()->getDecl()); if (Base->getNumVBases() == 0) continue; MarkVirtualMembersReferenced(Loc, Base); } } /// SetIvarInitializers - This routine builds initialization ASTs for the /// Objective-C implementation whose ivars need be initialized. void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { if (!getLangOpts().CPlusPlus) return; if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) { SmallVector ivars; CollectIvarsToConstructOrDestruct(OID, ivars); if (ivars.empty()) return; SmallVector AllToInit; for (unsigned i = 0; i < ivars.size(); i++) { FieldDecl *Field = ivars[i]; if (Field->isInvalidDecl()) continue; CXXCtorInitializer *Member; InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field); InitializationKind InitKind = InitializationKind::CreateDefault(ObjCImplementation->getLocation()); InitializationSequence InitSeq(*this, InitEntity, InitKind, None); ExprResult MemberInit = InitSeq.Perform(*this, InitEntity, InitKind, None); MemberInit = MaybeCreateExprWithCleanups(MemberInit); // Note, MemberInit could actually come back empty if no initialization // is required (e.g., because it would call a trivial default constructor) if (!MemberInit.get() || MemberInit.isInvalid()) continue; Member = new (Context) CXXCtorInitializer(Context, Field, SourceLocation(), SourceLocation(), MemberInit.getAs(), SourceLocation()); AllToInit.push_back(Member); // Be sure that the destructor is accessible and is marked as referenced. if (const RecordType *RecordTy = Context.getBaseElementType(Field->getType()) ->getAs()) { CXXRecordDecl *RD = cast(RecordTy->getDecl()); if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) { MarkFunctionReferenced(Field->getLocation(), Destructor); CheckDestructorAccess(Field->getLocation(), Destructor, PDiag(diag::err_access_dtor_ivar) << Context.getBaseElementType(Field->getType())); } } } ObjCImplementation->setIvarInitializers(Context, AllToInit.data(), AllToInit.size()); } } static void DelegatingCycleHelper(CXXConstructorDecl* Ctor, llvm::SmallSet &Valid, llvm::SmallSet &Invalid, llvm::SmallSet &Current, Sema &S) { if (Ctor->isInvalidDecl()) return; CXXConstructorDecl *Target = Ctor->getTargetConstructor(); // Target may not be determinable yet, for instance if this is a dependent // call in an uninstantiated template. if (Target) { const FunctionDecl *FNTarget = nullptr; (void)Target->hasBody(FNTarget); Target = const_cast( cast_or_null(FNTarget)); } CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(), // Avoid dereferencing a null pointer here. *TCanonical = Target? Target->getCanonicalDecl() : nullptr; if (!Current.insert(Canonical).second) return; // We know that beyond here, we aren't chaining into a cycle. if (!Target || !Target->isDelegatingConstructor() || Target->isInvalidDecl() || Valid.count(TCanonical)) { Valid.insert(Current.begin(), Current.end()); Current.clear(); // We've hit a cycle. } else if (TCanonical == Canonical || Invalid.count(TCanonical) || Current.count(TCanonical)) { // If we haven't diagnosed this cycle yet, do so now. if (!Invalid.count(TCanonical)) { S.Diag((*Ctor->init_begin())->getSourceLocation(), diag::warn_delegating_ctor_cycle) << Ctor; // Don't add a note for a function delegating directly to itself. if (TCanonical != Canonical) S.Diag(Target->getLocation(), diag::note_it_delegates_to); CXXConstructorDecl *C = Target; while (C->getCanonicalDecl() != Canonical) { const FunctionDecl *FNTarget = nullptr; (void)C->getTargetConstructor()->hasBody(FNTarget); assert(FNTarget && "Ctor cycle through bodiless function"); C = const_cast( cast(FNTarget)); S.Diag(C->getLocation(), diag::note_which_delegates_to); } } Invalid.insert(Current.begin(), Current.end()); Current.clear(); } else { DelegatingCycleHelper(Target, Valid, Invalid, Current, S); } } void Sema::CheckDelegatingCtorCycles() { llvm::SmallSet Valid, Invalid, Current; for (DelegatingCtorDeclsType::iterator I = DelegatingCtorDecls.begin(ExternalSource), E = DelegatingCtorDecls.end(); I != E; ++I) DelegatingCycleHelper(*I, Valid, Invalid, Current, *this); for (llvm::SmallSet::iterator CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI) (*CI)->setInvalidDecl(); } namespace { /// \brief AST visitor that finds references to the 'this' expression. class FindCXXThisExpr : public RecursiveASTVisitor { Sema &S; public: explicit FindCXXThisExpr(Sema &S) : S(S) { } bool VisitCXXThisExpr(CXXThisExpr *E) { S.Diag(E->getLocation(), diag::err_this_static_member_func) << E->isImplicit(); return false; } }; } bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) { TypeSourceInfo *TSInfo = Method->getTypeSourceInfo(); if (!TSInfo) return false; TypeLoc TL = TSInfo->getTypeLoc(); FunctionProtoTypeLoc ProtoTL = TL.getAs(); if (!ProtoTL) return false; // C++11 [expr.prim.general]p3: // [The expression this] shall not appear before the optional // cv-qualifier-seq and it shall not appear within the declaration of a // static member function (although its type and value category are defined // within a static member function as they are within a non-static member // function). [ Note: this is because declaration matching does not occur // until the complete declarator is known. - end note ] const FunctionProtoType *Proto = ProtoTL.getTypePtr(); FindCXXThisExpr Finder(*this); // If the return type came after the cv-qualifier-seq, check it now. if (Proto->hasTrailingReturn() && !Finder.TraverseTypeLoc(ProtoTL.getReturnLoc())) return true; // Check the exception specification. if (checkThisInStaticMemberFunctionExceptionSpec(Method)) return true; return checkThisInStaticMemberFunctionAttributes(Method); } bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) { TypeSourceInfo *TSInfo = Method->getTypeSourceInfo(); if (!TSInfo) return false; TypeLoc TL = TSInfo->getTypeLoc(); FunctionProtoTypeLoc ProtoTL = TL.getAs(); if (!ProtoTL) return false; const FunctionProtoType *Proto = ProtoTL.getTypePtr(); FindCXXThisExpr Finder(*this); switch (Proto->getExceptionSpecType()) { case EST_Unparsed: case EST_Uninstantiated: case EST_Unevaluated: case EST_BasicNoexcept: case EST_DynamicNone: case EST_MSAny: case EST_None: break; case EST_ComputedNoexcept: if (!Finder.TraverseStmt(Proto->getNoexceptExpr())) return true; LLVM_FALLTHROUGH; case EST_Dynamic: for (const auto &E : Proto->exceptions()) { if (!Finder.TraverseType(E)) return true; } break; } return false; } bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) { FindCXXThisExpr Finder(*this); // Check attributes. for (const auto *A : Method->attrs()) { // FIXME: This should be emitted by tblgen. Expr *Arg = nullptr; ArrayRef Args; if (const auto *G = dyn_cast(A)) Arg = G->getArg(); else if (const auto *G = dyn_cast(A)) Arg = G->getArg(); else if (const auto *AA = dyn_cast(A)) Args = llvm::makeArrayRef(AA->args_begin(), AA->args_size()); else if (const auto *AB = dyn_cast(A)) Args = llvm::makeArrayRef(AB->args_begin(), AB->args_size()); else if (const auto *ETLF = dyn_cast(A)) { Arg = ETLF->getSuccessValue(); Args = llvm::makeArrayRef(ETLF->args_begin(), ETLF->args_size()); } else if (const auto *STLF = dyn_cast(A)) { Arg = STLF->getSuccessValue(); Args = llvm::makeArrayRef(STLF->args_begin(), STLF->args_size()); } else if (const auto *LR = dyn_cast(A)) Arg = LR->getArg(); else if (const auto *LE = dyn_cast(A)) Args = llvm::makeArrayRef(LE->args_begin(), LE->args_size()); else if (const auto *RC = dyn_cast(A)) Args = llvm::makeArrayRef(RC->args_begin(), RC->args_size()); else if (const auto *AC = dyn_cast(A)) Args = llvm::makeArrayRef(AC->args_begin(), AC->args_size()); else if (const auto *AC = dyn_cast(A)) Args = llvm::makeArrayRef(AC->args_begin(), AC->args_size()); else if (const auto *RC = dyn_cast(A)) Args = llvm::makeArrayRef(RC->args_begin(), RC->args_size()); if (Arg && !Finder.TraverseStmt(Arg)) return true; for (unsigned I = 0, N = Args.size(); I != N; ++I) { if (!Finder.TraverseStmt(Args[I])) return true; } } return false; } void Sema::checkExceptionSpecification( bool IsTopLevel, ExceptionSpecificationType EST, ArrayRef DynamicExceptions, ArrayRef DynamicExceptionRanges, Expr *NoexceptExpr, SmallVectorImpl &Exceptions, FunctionProtoType::ExceptionSpecInfo &ESI) { Exceptions.clear(); ESI.Type = EST; if (EST == EST_Dynamic) { Exceptions.reserve(DynamicExceptions.size()); for (unsigned ei = 0, ee = DynamicExceptions.size(); ei != ee; ++ei) { // FIXME: Preserve type source info. QualType ET = GetTypeFromParser(DynamicExceptions[ei]); if (IsTopLevel) { SmallVector Unexpanded; collectUnexpandedParameterPacks(ET, Unexpanded); if (!Unexpanded.empty()) { DiagnoseUnexpandedParameterPacks( DynamicExceptionRanges[ei].getBegin(), UPPC_ExceptionType, Unexpanded); continue; } } // Check that the type is valid for an exception spec, and // drop it if not. if (!CheckSpecifiedExceptionType(ET, DynamicExceptionRanges[ei])) Exceptions.push_back(ET); } ESI.Exceptions = Exceptions; return; } if (EST == EST_ComputedNoexcept) { // If an error occurred, there's no expression here. if (NoexceptExpr) { assert((NoexceptExpr->isTypeDependent() || NoexceptExpr->getType()->getCanonicalTypeUnqualified() == Context.BoolTy) && "Parser should have made sure that the expression is boolean"); if (IsTopLevel && NoexceptExpr && DiagnoseUnexpandedParameterPack(NoexceptExpr)) { ESI.Type = EST_BasicNoexcept; return; } if (!NoexceptExpr->isValueDependent()) NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, nullptr, diag::err_noexcept_needs_constant_expression, /*AllowFold*/ false).get(); ESI.NoexceptExpr = NoexceptExpr; } return; } } void Sema::actOnDelayedExceptionSpecification(Decl *MethodD, ExceptionSpecificationType EST, SourceRange SpecificationRange, ArrayRef DynamicExceptions, ArrayRef DynamicExceptionRanges, Expr *NoexceptExpr) { if (!MethodD) return; // Dig out the method we're referring to. if (FunctionTemplateDecl *FunTmpl = dyn_cast(MethodD)) MethodD = FunTmpl->getTemplatedDecl(); CXXMethodDecl *Method = dyn_cast(MethodD); if (!Method) return; // Check the exception specification. llvm::SmallVector Exceptions; FunctionProtoType::ExceptionSpecInfo ESI; checkExceptionSpecification(/*IsTopLevel*/true, EST, DynamicExceptions, DynamicExceptionRanges, NoexceptExpr, Exceptions, ESI); // Update the exception specification on the function type. Context.adjustExceptionSpec(Method, ESI, /*AsWritten*/true); if (Method->isStatic()) checkThisInStaticMemberFunctionExceptionSpec(Method); if (Method->isVirtual()) { // Check overrides, which we previously had to delay. for (CXXMethodDecl::method_iterator O = Method->begin_overridden_methods(), OEnd = Method->end_overridden_methods(); O != OEnd; ++O) CheckOverridingFunctionExceptionSpec(Method, *O); } } /// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class. /// MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, SourceLocation DeclStart, Declarator &D, Expr *BitWidth, InClassInitStyle InitStyle, AccessSpecifier AS, AttributeList *MSPropertyAttr) { IdentifierInfo *II = D.getIdentifier(); if (!II) { Diag(DeclStart, diag::err_anonymous_property); return nullptr; } SourceLocation Loc = D.getIdentifierLoc(); TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType T = TInfo->getType(); if (getLangOpts().CPlusPlus) { CheckExtraCXXDefaultArguments(D); if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, UPPC_DataMemberType)) { D.setInvalidType(); T = Context.IntTy; TInfo = Context.getTrivialTypeSourceInfo(T, Loc); } } DiagnoseFunctionSpecifiers(D.getDeclSpec()); if (D.getDeclSpec().isInlineSpecified()) Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function) << getLangOpts().CPlusPlus1z; if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), diag::err_invalid_thread) << DeclSpec::getSpecifierName(TSCS); // Check to see if this name was declared as a member previously NamedDecl *PrevDecl = nullptr; LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration); LookupName(Previous, S); switch (Previous.getResultKind()) { case LookupResult::Found: case LookupResult::FoundUnresolvedValue: PrevDecl = Previous.getAsSingle(); break; case LookupResult::FoundOverloaded: PrevDecl = Previous.getRepresentativeDecl(); break; case LookupResult::NotFound: case LookupResult::NotFoundInCurrentInstantiation: case LookupResult::Ambiguous: break; } if (PrevDecl && PrevDecl->isTemplateParameter()) { // Maybe we will complain about the shadowed template parameter. DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); // Just pretend that we didn't see the previous declaration. PrevDecl = nullptr; } if (PrevDecl && !isDeclInScope(PrevDecl, Record, S)) PrevDecl = nullptr; SourceLocation TSSL = D.getLocStart(); const AttributeList::PropertyData &Data = MSPropertyAttr->getPropertyData(); MSPropertyDecl *NewPD = MSPropertyDecl::Create( Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId); ProcessDeclAttributes(TUScope, NewPD, D); NewPD->setAccess(AS); if (NewPD->isInvalidDecl()) Record->setInvalidDecl(); if (D.getDeclSpec().isModulePrivateSpecified()) NewPD->setModulePrivate(); if (NewPD->isInvalidDecl() && PrevDecl) { // Don't introduce NewFD into scope; there's already something // with the same name in the same scope. } else if (II) { PushOnScopeChains(NewPD, S); } else Record->addDecl(NewPD); return NewPD; } Index: head/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- head/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (revision 326908) +++ head/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (revision 326909) @@ -1,5207 +1,5208 @@ //===--- SemaTemplateInstantiateDecl.cpp - C++ Template Decl Instantiation ===/ // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. //===----------------------------------------------------------------------===/ // // This file implements C++ template instantiation for declarations. // //===----------------------------------------------------------------------===/ #include "clang/Sema/SemaInternal.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/DependentDiagnostic.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/TypeLoc.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Template.h" using namespace clang; static bool isDeclWithinFunction(const Decl *D) { const DeclContext *DC = D->getDeclContext(); if (DC->isFunctionOrMethod()) return true; if (DC->isRecord()) return cast(DC)->isLocalClass(); return false; } template static bool SubstQualifier(Sema &SemaRef, const DeclT *OldDecl, DeclT *NewDecl, const MultiLevelTemplateArgumentList &TemplateArgs) { if (!OldDecl->getQualifierLoc()) return false; assert((NewDecl->getFriendObjectKind() || !OldDecl->getLexicalDeclContext()->isDependentContext()) && "non-friend with qualified name defined in dependent context"); Sema::ContextRAII SavedContext( SemaRef, const_cast(NewDecl->getFriendObjectKind() ? NewDecl->getLexicalDeclContext() : OldDecl->getLexicalDeclContext())); NestedNameSpecifierLoc NewQualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(), TemplateArgs); if (!NewQualifierLoc) return true; NewDecl->setQualifierInfo(NewQualifierLoc); return false; } bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl, DeclaratorDecl *NewDecl) { return ::SubstQualifier(SemaRef, OldDecl, NewDecl, TemplateArgs); } bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl, TagDecl *NewDecl) { return ::SubstQualifier(SemaRef, OldDecl, NewDecl, TemplateArgs); } // Include attribute instantiation code. #include "clang/Sema/AttrTemplateInstantiate.inc" static void instantiateDependentAlignedAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const AlignedAttr *Aligned, Decl *New, bool IsPackExpansion) { if (Aligned->isAlignmentExpr()) { // The alignment expression is a constant expression. EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); ExprResult Result = S.SubstExpr(Aligned->getAlignmentExpr(), TemplateArgs); if (!Result.isInvalid()) S.AddAlignedAttr(Aligned->getLocation(), New, Result.getAs(), Aligned->getSpellingListIndex(), IsPackExpansion); } else { TypeSourceInfo *Result = S.SubstType(Aligned->getAlignmentType(), TemplateArgs, Aligned->getLocation(), DeclarationName()); if (Result) S.AddAlignedAttr(Aligned->getLocation(), New, Result, Aligned->getSpellingListIndex(), IsPackExpansion); } } static void instantiateDependentAlignedAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const AlignedAttr *Aligned, Decl *New) { if (!Aligned->isPackExpansion()) { instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, false); return; } SmallVector Unexpanded; if (Aligned->isAlignmentExpr()) S.collectUnexpandedParameterPacks(Aligned->getAlignmentExpr(), Unexpanded); else S.collectUnexpandedParameterPacks(Aligned->getAlignmentType()->getTypeLoc(), Unexpanded); assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); // Determine whether we can expand this attribute pack yet. bool Expand = true, RetainExpansion = false; Optional NumExpansions; // FIXME: Use the actual location of the ellipsis. SourceLocation EllipsisLoc = Aligned->getLocation(); if (S.CheckParameterPacksForExpansion(EllipsisLoc, Aligned->getRange(), Unexpanded, TemplateArgs, Expand, RetainExpansion, NumExpansions)) return; if (!Expand) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, -1); instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, true); } else { for (unsigned I = 0; I != *NumExpansions; ++I) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, I); instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, false); } } } static void instantiateDependentAssumeAlignedAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const AssumeAlignedAttr *Aligned, Decl *New) { // The alignment expression is a constant expression. EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); Expr *E, *OE = nullptr; ExprResult Result = S.SubstExpr(Aligned->getAlignment(), TemplateArgs); if (Result.isInvalid()) return; E = Result.getAs(); if (Aligned->getOffset()) { Result = S.SubstExpr(Aligned->getOffset(), TemplateArgs); if (Result.isInvalid()) return; OE = Result.getAs(); } S.AddAssumeAlignedAttr(Aligned->getLocation(), New, E, OE, Aligned->getSpellingListIndex()); } static void instantiateDependentAlignValueAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const AlignValueAttr *Aligned, Decl *New) { // The alignment expression is a constant expression. EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); ExprResult Result = S.SubstExpr(Aligned->getAlignment(), TemplateArgs); if (!Result.isInvalid()) S.AddAlignValueAttr(Aligned->getLocation(), New, Result.getAs(), Aligned->getSpellingListIndex()); } static void instantiateDependentAllocAlignAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const AllocAlignAttr *Align, Decl *New) { Expr *Param = IntegerLiteral::Create( S.getASTContext(), llvm::APInt(64, Align->getParamIndex()), S.getASTContext().UnsignedLongLongTy, Align->getLocation()); S.AddAllocAlignAttr(Align->getLocation(), New, Param, Align->getSpellingListIndex()); } static Expr *instantiateDependentFunctionAttrCondition( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const Attr *A, Expr *OldCond, const Decl *Tmpl, FunctionDecl *New) { Expr *Cond = nullptr; { Sema::ContextRAII SwitchContext(S, New); EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); ExprResult Result = S.SubstExpr(OldCond, TemplateArgs); if (Result.isInvalid()) return nullptr; Cond = Result.getAs(); } if (!Cond->isTypeDependent()) { ExprResult Converted = S.PerformContextuallyConvertToBool(Cond); if (Converted.isInvalid()) return nullptr; Cond = Converted.get(); } SmallVector Diags; if (OldCond->isValueDependent() && !Cond->isValueDependent() && !Expr::isPotentialConstantExprUnevaluated(Cond, New, Diags)) { S.Diag(A->getLocation(), diag::err_attr_cond_never_constant_expr) << A; for (const auto &P : Diags) S.Diag(P.first, P.second); return nullptr; } return Cond; } static void instantiateDependentEnableIfAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const EnableIfAttr *EIA, const Decl *Tmpl, FunctionDecl *New) { Expr *Cond = instantiateDependentFunctionAttrCondition( S, TemplateArgs, EIA, EIA->getCond(), Tmpl, New); if (Cond) New->addAttr(new (S.getASTContext()) EnableIfAttr( EIA->getLocation(), S.getASTContext(), Cond, EIA->getMessage(), EIA->getSpellingListIndex())); } static void instantiateDependentDiagnoseIfAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const DiagnoseIfAttr *DIA, const Decl *Tmpl, FunctionDecl *New) { Expr *Cond = instantiateDependentFunctionAttrCondition( S, TemplateArgs, DIA, DIA->getCond(), Tmpl, New); if (Cond) New->addAttr(new (S.getASTContext()) DiagnoseIfAttr( DIA->getLocation(), S.getASTContext(), Cond, DIA->getMessage(), DIA->getDiagnosticType(), DIA->getArgDependent(), New, DIA->getSpellingListIndex())); } // Constructs and adds to New a new instance of CUDALaunchBoundsAttr using // template A as the base and arguments from TemplateArgs. static void instantiateDependentCUDALaunchBoundsAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const CUDALaunchBoundsAttr &Attr, Decl *New) { // The alignment expression is a constant expression. EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); ExprResult Result = S.SubstExpr(Attr.getMaxThreads(), TemplateArgs); if (Result.isInvalid()) return; Expr *MaxThreads = Result.getAs(); Expr *MinBlocks = nullptr; if (Attr.getMinBlocks()) { Result = S.SubstExpr(Attr.getMinBlocks(), TemplateArgs); if (Result.isInvalid()) return; MinBlocks = Result.getAs(); } S.AddLaunchBoundsAttr(Attr.getLocation(), New, MaxThreads, MinBlocks, Attr.getSpellingListIndex()); } static void instantiateDependentModeAttr(Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const ModeAttr &Attr, Decl *New) { S.AddModeAttr(Attr.getRange(), New, Attr.getMode(), Attr.getSpellingListIndex(), /*InInstantiation=*/true); } /// Instantiation of 'declare simd' attribute and its arguments. static void instantiateOMPDeclareSimdDeclAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const OMPDeclareSimdDeclAttr &Attr, Decl *New) { // Allow 'this' in clauses with varlists. if (auto *FTD = dyn_cast(New)) New = FTD->getTemplatedDecl(); auto *FD = cast(New); auto *ThisContext = dyn_cast_or_null(FD->getDeclContext()); SmallVector Uniforms, Aligneds, Alignments, Linears, Steps; SmallVector LinModifiers; auto &&Subst = [&](Expr *E) -> ExprResult { if (auto *DRE = dyn_cast(E->IgnoreParenImpCasts())) if (auto *PVD = dyn_cast(DRE->getDecl())) { Sema::ContextRAII SavedContext(S, FD); LocalInstantiationScope Local(S); if (FD->getNumParams() > PVD->getFunctionScopeIndex()) Local.InstantiatedLocal( PVD, FD->getParamDecl(PVD->getFunctionScopeIndex())); return S.SubstExpr(E, TemplateArgs); } Sema::CXXThisScopeRAII ThisScope(S, ThisContext, /*TypeQuals=*/0, FD->isCXXInstanceMember()); return S.SubstExpr(E, TemplateArgs); }; ExprResult Simdlen; if (auto *E = Attr.getSimdlen()) Simdlen = Subst(E); if (Attr.uniforms_size() > 0) { for(auto *E : Attr.uniforms()) { ExprResult Inst = Subst(E); if (Inst.isInvalid()) continue; Uniforms.push_back(Inst.get()); } } auto AI = Attr.alignments_begin(); for (auto *E : Attr.aligneds()) { ExprResult Inst = Subst(E); if (Inst.isInvalid()) continue; Aligneds.push_back(Inst.get()); Inst = ExprEmpty(); if (*AI) Inst = S.SubstExpr(*AI, TemplateArgs); Alignments.push_back(Inst.get()); ++AI; } auto SI = Attr.steps_begin(); for (auto *E : Attr.linears()) { ExprResult Inst = Subst(E); if (Inst.isInvalid()) continue; Linears.push_back(Inst.get()); Inst = ExprEmpty(); if (*SI) Inst = S.SubstExpr(*SI, TemplateArgs); Steps.push_back(Inst.get()); ++SI; } LinModifiers.append(Attr.modifiers_begin(), Attr.modifiers_end()); (void)S.ActOnOpenMPDeclareSimdDirective( S.ConvertDeclToDeclGroup(New), Attr.getBranchState(), Simdlen.get(), Uniforms, Aligneds, Alignments, Linears, LinModifiers, Steps, Attr.getRange()); } static bool DeclContainsAttr(const Decl *D, const Attr *NewAttr) { if (!D->hasAttrs() || NewAttr->duplicatesAllowed()) return false; return llvm::find_if(D->getAttrs(), [NewAttr](const Attr *Attr) { return Attr->getKind() == NewAttr->getKind(); }) != D->getAttrs().end(); } void Sema::InstantiateAttrsForDecl( const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *OuterMostScope) { if (NamedDecl *ND = dyn_cast(New)) { for (const auto *TmplAttr : Tmpl->attrs()) { // FIXME: If any of the special case versions from InstantiateAttrs become // applicable to template declaration, we'll need to add them here. CXXThisScopeRAII ThisScope( *this, dyn_cast_or_null(ND->getDeclContext()), /*TypeQuals*/ 0, ND->isCXXInstanceMember()); Attr *NewAttr = sema::instantiateTemplateAttributeForDecl( TmplAttr, Context, *this, TemplateArgs); if (NewAttr && !DeclContainsAttr(New, NewAttr)) New->addAttr(NewAttr); } } } void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *OuterMostScope) { for (const auto *TmplAttr : Tmpl->attrs()) { // FIXME: This should be generalized to more than just the AlignedAttr. const AlignedAttr *Aligned = dyn_cast(TmplAttr); if (Aligned && Aligned->isAlignmentDependent()) { instantiateDependentAlignedAttr(*this, TemplateArgs, Aligned, New); continue; } const AssumeAlignedAttr *AssumeAligned = dyn_cast(TmplAttr); if (AssumeAligned) { instantiateDependentAssumeAlignedAttr(*this, TemplateArgs, AssumeAligned, New); continue; } const AlignValueAttr *AlignValue = dyn_cast(TmplAttr); if (AlignValue) { instantiateDependentAlignValueAttr(*this, TemplateArgs, AlignValue, New); continue; } if (const auto *AllocAlign = dyn_cast(TmplAttr)) { instantiateDependentAllocAlignAttr(*this, TemplateArgs, AllocAlign, New); continue; } if (const auto *EnableIf = dyn_cast(TmplAttr)) { instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl, cast(New)); continue; } if (const auto *DiagnoseIf = dyn_cast(TmplAttr)) { instantiateDependentDiagnoseIfAttr(*this, TemplateArgs, DiagnoseIf, Tmpl, cast(New)); continue; } if (const CUDALaunchBoundsAttr *CUDALaunchBounds = dyn_cast(TmplAttr)) { instantiateDependentCUDALaunchBoundsAttr(*this, TemplateArgs, *CUDALaunchBounds, New); continue; } if (const ModeAttr *Mode = dyn_cast(TmplAttr)) { instantiateDependentModeAttr(*this, TemplateArgs, *Mode, New); continue; } if (const auto *OMPAttr = dyn_cast(TmplAttr)) { instantiateOMPDeclareSimdDeclAttr(*this, TemplateArgs, *OMPAttr, New); continue; } // Existing DLL attribute on the instantiation takes precedence. if (TmplAttr->getKind() == attr::DLLExport || TmplAttr->getKind() == attr::DLLImport) { if (New->hasAttr() || New->hasAttr()) { continue; } } if (auto ABIAttr = dyn_cast(TmplAttr)) { AddParameterABIAttr(ABIAttr->getRange(), New, ABIAttr->getABI(), ABIAttr->getSpellingListIndex()); continue; } if (isa(TmplAttr) || isa(TmplAttr)) { AddNSConsumedAttr(TmplAttr->getRange(), New, TmplAttr->getSpellingListIndex(), isa(TmplAttr), /*template instantiation*/ true); continue; } assert(!TmplAttr->isPackExpansion()); if (TmplAttr->isLateParsed() && LateAttrs) { // Late parsed attributes must be instantiated and attached after the // enclosing class has been instantiated. See Sema::InstantiateClass. LocalInstantiationScope *Saved = nullptr; if (CurrentInstantiationScope) Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope); LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New)); } else { // Allow 'this' within late-parsed attributes. NamedDecl *ND = dyn_cast(New); CXXRecordDecl *ThisContext = dyn_cast_or_null(ND->getDeclContext()); CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0, ND && ND->isCXXInstanceMember()); Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs); if (NewAttr && !DeclContainsAttr(New, NewAttr)) New->addAttr(NewAttr); } } } /// Get the previous declaration of a declaration for the purposes of template /// instantiation. If this finds a previous declaration, then the previous /// declaration of the instantiation of D should be an instantiation of the /// result of this function. template static DeclT *getPreviousDeclForInstantiation(DeclT *D) { DeclT *Result = D->getPreviousDecl(); // If the declaration is within a class, and the previous declaration was // merged from a different definition of that class, then we don't have a // previous declaration for the purpose of template instantiation. if (Result && isa(D->getDeclContext()) && D->getLexicalDeclContext() != Result->getLexicalDeclContext()) return nullptr; return Result; } Decl * TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) { llvm_unreachable("Translation units cannot be instantiated"); } Decl * TemplateDeclInstantiator::VisitPragmaCommentDecl(PragmaCommentDecl *D) { llvm_unreachable("pragma comment cannot be instantiated"); } Decl *TemplateDeclInstantiator::VisitPragmaDetectMismatchDecl( PragmaDetectMismatchDecl *D) { llvm_unreachable("pragma comment cannot be instantiated"); } Decl * TemplateDeclInstantiator::VisitExternCContextDecl(ExternCContextDecl *D) { llvm_unreachable("extern \"C\" context cannot be instantiated"); } Decl * TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) { LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getIdentifier()); Owner->addDecl(Inst); return Inst; } Decl * TemplateDeclInstantiator::VisitNamespaceDecl(NamespaceDecl *D) { llvm_unreachable("Namespaces cannot be instantiated"); } Decl * TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { NamespaceAliasDecl *Inst = NamespaceAliasDecl::Create(SemaRef.Context, Owner, D->getNamespaceLoc(), D->getAliasLoc(), D->getIdentifier(), D->getQualifierLoc(), D->getTargetNameLoc(), D->getNamespace()); Owner->addDecl(Inst); return Inst; } Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias) { bool Invalid = false; TypeSourceInfo *DI = D->getTypeSourceInfo(); if (DI->getType()->isInstantiationDependentType() || DI->getType()->isVariablyModifiedType()) { DI = SemaRef.SubstType(DI, TemplateArgs, D->getLocation(), D->getDeclName()); if (!DI) { Invalid = true; DI = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.Context.IntTy); } } else { SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType()); } // HACK: g++ has a bug where it gets the value kind of ?: wrong. // libstdc++ relies upon this bug in its implementation of common_type. // If we happen to be processing that implementation, fake up the g++ ?: // semantics. See LWG issue 2141 for more information on the bug. const DecltypeType *DT = DI->getType()->getAs(); CXXRecordDecl *RD = dyn_cast(D->getDeclContext()); if (DT && RD && isa(DT->getUnderlyingExpr()) && DT->isReferenceType() && RD->getEnclosingNamespaceContext() == SemaRef.getStdNamespace() && RD->getIdentifier() && RD->getIdentifier()->isStr("common_type") && D->getIdentifier() && D->getIdentifier()->isStr("type") && SemaRef.getSourceManager().isInSystemHeader(D->getLocStart())) // Fold it to the (non-reference) type which g++ would have produced. DI = SemaRef.Context.getTrivialTypeSourceInfo( DI->getType().getNonReferenceType()); // Create the new typedef TypedefNameDecl *Typedef; if (IsTypeAlias) Typedef = TypeAliasDecl::Create(SemaRef.Context, Owner, D->getLocStart(), D->getLocation(), D->getIdentifier(), DI); else Typedef = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocStart(), D->getLocation(), D->getIdentifier(), DI); if (Invalid) Typedef->setInvalidDecl(); // If the old typedef was the name for linkage purposes of an anonymous // tag decl, re-establish that relationship for the new typedef. if (const TagType *oldTagType = D->getUnderlyingType()->getAs()) { TagDecl *oldTag = oldTagType->getDecl(); if (oldTag->getTypedefNameForAnonDecl() == D && !Invalid) { TagDecl *newTag = DI->getType()->castAs()->getDecl(); assert(!newTag->hasNameForLinkage()); newTag->setTypedefNameForAnonDecl(Typedef); } } if (TypedefNameDecl *Prev = getPreviousDeclForInstantiation(D)) { NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev, TemplateArgs); if (!InstPrev) return nullptr; TypedefNameDecl *InstPrevTypedef = cast(InstPrev); // If the typedef types are not identical, reject them. SemaRef.isIncompatibleTypedef(InstPrevTypedef, Typedef); Typedef->setPreviousDecl(InstPrevTypedef); } SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef); Typedef->setAccess(D->getAccess()); return Typedef; } Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/false); if (Typedef) Owner->addDecl(Typedef); return Typedef; } Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) { Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/true); if (Typedef) Owner->addDecl(Typedef); return Typedef; } Decl * TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { // Create a local instantiation scope for this type alias template, which // will contain the instantiations of the template parameters. LocalInstantiationScope Scope(SemaRef); TemplateParameterList *TempParams = D->getTemplateParameters(); TemplateParameterList *InstParams = SubstTemplateParams(TempParams); if (!InstParams) return nullptr; TypeAliasDecl *Pattern = D->getTemplatedDecl(); TypeAliasTemplateDecl *PrevAliasTemplate = nullptr; if (getPreviousDeclForInstantiation(Pattern)) { DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); if (!Found.empty()) { PrevAliasTemplate = dyn_cast(Found.front()); } } TypeAliasDecl *AliasInst = cast_or_null( InstantiateTypedefNameDecl(Pattern, /*IsTypeAlias=*/true)); if (!AliasInst) return nullptr; TypeAliasTemplateDecl *Inst = TypeAliasTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getDeclName(), InstParams, AliasInst); AliasInst->setDescribedAliasTemplate(Inst); if (PrevAliasTemplate) Inst->setPreviousDecl(PrevAliasTemplate); Inst->setAccess(D->getAccess()); if (!PrevAliasTemplate) Inst->setInstantiatedFromMemberTemplate(D); Owner->addDecl(Inst); return Inst; } Decl *TemplateDeclInstantiator::VisitBindingDecl(BindingDecl *D) { auto *NewBD = BindingDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getIdentifier()); + NewBD->setReferenced(D->isReferenced()); SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewBD); return NewBD; } Decl *TemplateDeclInstantiator::VisitDecompositionDecl(DecompositionDecl *D) { // Transform the bindings first. SmallVector NewBindings; for (auto *OldBD : D->bindings()) NewBindings.push_back(cast(VisitBindingDecl(OldBD))); ArrayRef NewBindingArray = NewBindings; auto *NewDD = cast_or_null( VisitVarDecl(D, /*InstantiatingVarTemplate=*/false, &NewBindingArray)); if (!NewDD || NewDD->isInvalidDecl()) for (auto *NewBD : NewBindings) NewBD->setInvalidDecl(); return NewDD; } Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { return VisitVarDecl(D, /*InstantiatingVarTemplate=*/false); } Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate, ArrayRef *Bindings) { // Do substitution on the type of the declaration TypeSourceInfo *DI = SemaRef.SubstType( D->getTypeSourceInfo(), TemplateArgs, D->getTypeSpecStartLoc(), D->getDeclName(), /*AllowDeducedTST*/true); if (!DI) return nullptr; if (DI->getType()->isFunctionType()) { SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function) << D->isStaticDataMember() << DI->getType(); return nullptr; } DeclContext *DC = Owner; if (D->isLocalExternDecl()) SemaRef.adjustContextForLocalExternDecl(DC); // Build the instantiated declaration. VarDecl *Var; if (Bindings) Var = DecompositionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(), D->getLocation(), DI->getType(), DI, D->getStorageClass(), *Bindings); else Var = VarDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(), D->getLocation(), D->getIdentifier(), DI->getType(), DI, D->getStorageClass()); // In ARC, infer 'retaining' for variables of retainable type. if (SemaRef.getLangOpts().ObjCAutoRefCount && SemaRef.inferObjCARCLifetime(Var)) Var->setInvalidDecl(); // Substitute the nested name specifier, if any. if (SubstQualifier(D, Var)) return nullptr; SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner, StartingScope, InstantiatingVarTemplate); if (D->isNRVOVariable()) { QualType ReturnType = cast(DC)->getReturnType(); if (SemaRef.isCopyElisionCandidate(ReturnType, Var, false)) Var->setNRVOVariable(true); } Var->setImplicit(D->isImplicit()); return Var; } Decl *TemplateDeclInstantiator::VisitAccessSpecDecl(AccessSpecDecl *D) { AccessSpecDecl* AD = AccessSpecDecl::Create(SemaRef.Context, D->getAccess(), Owner, D->getAccessSpecifierLoc(), D->getColonLoc()); Owner->addHiddenDecl(AD); return AD; } Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { bool Invalid = false; TypeSourceInfo *DI = D->getTypeSourceInfo(); if (DI->getType()->isInstantiationDependentType() || DI->getType()->isVariablyModifiedType()) { DI = SemaRef.SubstType(DI, TemplateArgs, D->getLocation(), D->getDeclName()); if (!DI) { DI = D->getTypeSourceInfo(); Invalid = true; } else if (DI->getType()->isFunctionType()) { // C++ [temp.arg.type]p3: // If a declaration acquires a function type through a type // dependent on a template-parameter and this causes a // declaration that does not use the syntactic form of a // function declarator to have function type, the program is // ill-formed. SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function) << DI->getType(); Invalid = true; } } else { SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType()); } Expr *BitWidth = D->getBitWidth(); if (Invalid) BitWidth = nullptr; else if (BitWidth) { // The bit-width expression is a constant expression. EnterExpressionEvaluationContext Unevaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); ExprResult InstantiatedBitWidth = SemaRef.SubstExpr(BitWidth, TemplateArgs); if (InstantiatedBitWidth.isInvalid()) { Invalid = true; BitWidth = nullptr; } else BitWidth = InstantiatedBitWidth.getAs(); } FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(), DI->getType(), DI, cast(Owner), D->getLocation(), D->isMutable(), BitWidth, D->getInClassInitStyle(), D->getInnerLocStart(), D->getAccess(), nullptr); if (!Field) { cast(Owner)->setInvalidDecl(); return nullptr; } SemaRef.InstantiateAttrs(TemplateArgs, D, Field, LateAttrs, StartingScope); if (Field->hasAttrs()) SemaRef.CheckAlignasUnderalignment(Field); if (Invalid) Field->setInvalidDecl(); if (!Field->getDeclName()) { // Keep track of where this decl came from. SemaRef.Context.setInstantiatedFromUnnamedFieldDecl(Field, D); } if (CXXRecordDecl *Parent= dyn_cast(Field->getDeclContext())) { if (Parent->isAnonymousStructOrUnion() && Parent->getRedeclContext()->isFunctionOrMethod()) SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Field); } Field->setImplicit(D->isImplicit()); Field->setAccess(D->getAccess()); Owner->addDecl(Field); return Field; } Decl *TemplateDeclInstantiator::VisitMSPropertyDecl(MSPropertyDecl *D) { bool Invalid = false; TypeSourceInfo *DI = D->getTypeSourceInfo(); if (DI->getType()->isVariablyModifiedType()) { SemaRef.Diag(D->getLocation(), diag::err_property_is_variably_modified) << D; Invalid = true; } else if (DI->getType()->isInstantiationDependentType()) { DI = SemaRef.SubstType(DI, TemplateArgs, D->getLocation(), D->getDeclName()); if (!DI) { DI = D->getTypeSourceInfo(); Invalid = true; } else if (DI->getType()->isFunctionType()) { // C++ [temp.arg.type]p3: // If a declaration acquires a function type through a type // dependent on a template-parameter and this causes a // declaration that does not use the syntactic form of a // function declarator to have function type, the program is // ill-formed. SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function) << DI->getType(); Invalid = true; } } else { SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType()); } MSPropertyDecl *Property = MSPropertyDecl::Create( SemaRef.Context, Owner, D->getLocation(), D->getDeclName(), DI->getType(), DI, D->getLocStart(), D->getGetterId(), D->getSetterId()); SemaRef.InstantiateAttrs(TemplateArgs, D, Property, LateAttrs, StartingScope); if (Invalid) Property->setInvalidDecl(); Property->setAccess(D->getAccess()); Owner->addDecl(Property); return Property; } Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) { NamedDecl **NamedChain = new (SemaRef.Context)NamedDecl*[D->getChainingSize()]; int i = 0; for (auto *PI : D->chain()) { NamedDecl *Next = SemaRef.FindInstantiatedDecl(D->getLocation(), PI, TemplateArgs); if (!Next) return nullptr; NamedChain[i++] = Next; } QualType T = cast(NamedChain[i-1])->getType(); IndirectFieldDecl *IndirectField = IndirectFieldDecl::Create( SemaRef.Context, Owner, D->getLocation(), D->getIdentifier(), T, {NamedChain, D->getChainingSize()}); for (const auto *Attr : D->attrs()) IndirectField->addAttr(Attr->clone(SemaRef.Context)); IndirectField->setImplicit(D->isImplicit()); IndirectField->setAccess(D->getAccess()); Owner->addDecl(IndirectField); return IndirectField; } Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { // Handle friend type expressions by simply substituting template // parameters into the pattern type and checking the result. if (TypeSourceInfo *Ty = D->getFriendType()) { TypeSourceInfo *InstTy; // If this is an unsupported friend, don't bother substituting template // arguments into it. The actual type referred to won't be used by any // parts of Clang, and may not be valid for instantiating. Just use the // same info for the instantiated friend. if (D->isUnsupportedFriend()) { InstTy = Ty; } else { InstTy = SemaRef.SubstType(Ty, TemplateArgs, D->getLocation(), DeclarationName()); } if (!InstTy) return nullptr; FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocStart(), D->getFriendLoc(), InstTy); if (!FD) return nullptr; FD->setAccess(AS_public); FD->setUnsupportedFriend(D->isUnsupportedFriend()); Owner->addDecl(FD); return FD; } NamedDecl *ND = D->getFriendDecl(); assert(ND && "friend decl must be a decl or a type!"); // All of the Visit implementations for the various potential friend // declarations have to be carefully written to work for friend // objects, with the most important detail being that the target // decl should almost certainly not be placed in Owner. Decl *NewND = Visit(ND); if (!NewND) return nullptr; FriendDecl *FD = FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(), cast(NewND), D->getFriendLoc()); FD->setAccess(AS_public); FD->setUnsupportedFriend(D->isUnsupportedFriend()); Owner->addDecl(FD); return FD; } Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { Expr *AssertExpr = D->getAssertExpr(); // The expression in a static assertion is a constant expression. EnterExpressionEvaluationContext Unevaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); ExprResult InstantiatedAssertExpr = SemaRef.SubstExpr(AssertExpr, TemplateArgs); if (InstantiatedAssertExpr.isInvalid()) return nullptr; return SemaRef.BuildStaticAssertDeclaration(D->getLocation(), InstantiatedAssertExpr.get(), D->getMessage(), D->getRParenLoc(), D->isFailed()); } Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { EnumDecl *PrevDecl = nullptr; if (EnumDecl *PatternPrev = getPreviousDeclForInstantiation(D)) { NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), PatternPrev, TemplateArgs); if (!Prev) return nullptr; PrevDecl = cast(Prev); } EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, D->getLocStart(), D->getLocation(), D->getIdentifier(), PrevDecl, D->isScoped(), D->isScopedUsingClassTag(), D->isFixed()); if (D->isFixed()) { if (TypeSourceInfo *TI = D->getIntegerTypeSourceInfo()) { // If we have type source information for the underlying type, it means it // has been explicitly set by the user. Perform substitution on it before // moving on. SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); TypeSourceInfo *NewTI = SemaRef.SubstType(TI, TemplateArgs, UnderlyingLoc, DeclarationName()); if (!NewTI || SemaRef.CheckEnumUnderlyingType(NewTI)) Enum->setIntegerType(SemaRef.Context.IntTy); else Enum->setIntegerTypeSourceInfo(NewTI); } else { assert(!D->getIntegerType()->isDependentType() && "Dependent type without type source info"); Enum->setIntegerType(D->getIntegerType()); } } SemaRef.InstantiateAttrs(TemplateArgs, D, Enum); Enum->setInstantiationOfMemberEnum(D, TSK_ImplicitInstantiation); Enum->setAccess(D->getAccess()); // Forward the mangling number from the template to the instantiated decl. SemaRef.Context.setManglingNumber(Enum, SemaRef.Context.getManglingNumber(D)); // See if the old tag was defined along with a declarator. // If it did, mark the new tag as being associated with that declarator. if (DeclaratorDecl *DD = SemaRef.Context.getDeclaratorForUnnamedTagDecl(D)) SemaRef.Context.addDeclaratorForUnnamedTagDecl(Enum, DD); // See if the old tag was defined along with a typedef. // If it did, mark the new tag as being associated with that typedef. if (TypedefNameDecl *TND = SemaRef.Context.getTypedefNameForUnnamedTagDecl(D)) SemaRef.Context.addTypedefNameForUnnamedTagDecl(Enum, TND); if (SubstQualifier(D, Enum)) return nullptr; Owner->addDecl(Enum); EnumDecl *Def = D->getDefinition(); if (Def && Def != D) { // If this is an out-of-line definition of an enum member template, check // that the underlying types match in the instantiation of both // declarations. if (TypeSourceInfo *TI = Def->getIntegerTypeSourceInfo()) { SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); QualType DefnUnderlying = SemaRef.SubstType(TI->getType(), TemplateArgs, UnderlyingLoc, DeclarationName()); SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(), DefnUnderlying, /*EnumUnderlyingIsImplicit=*/false, Enum); } } // C++11 [temp.inst]p1: The implicit instantiation of a class template // specialization causes the implicit instantiation of the declarations, but // not the definitions of scoped member enumerations. // // DR1484 clarifies that enumeration definitions inside of a template // declaration aren't considered entities that can be separately instantiated // from the rest of the entity they are declared inside of. if (isDeclWithinFunction(D) ? D == Def : Def && !Enum->isScoped()) { SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum); InstantiateEnumDefinition(Enum, Def); } return Enum; } void TemplateDeclInstantiator::InstantiateEnumDefinition( EnumDecl *Enum, EnumDecl *Pattern) { Enum->startDefinition(); // Update the location to refer to the definition. Enum->setLocation(Pattern->getLocation()); SmallVector Enumerators; EnumConstantDecl *LastEnumConst = nullptr; for (auto *EC : Pattern->enumerators()) { // The specified value for the enumerator. ExprResult Value((Expr *)nullptr); if (Expr *UninstValue = EC->getInitExpr()) { // The enumerator's value expression is a constant expression. EnterExpressionEvaluationContext Unevaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); Value = SemaRef.SubstExpr(UninstValue, TemplateArgs); } // Drop the initial value and continue. bool isInvalid = false; if (Value.isInvalid()) { Value = nullptr; isInvalid = true; } EnumConstantDecl *EnumConst = SemaRef.CheckEnumConstant(Enum, LastEnumConst, EC->getLocation(), EC->getIdentifier(), Value.get()); if (isInvalid) { if (EnumConst) EnumConst->setInvalidDecl(); Enum->setInvalidDecl(); } if (EnumConst) { SemaRef.InstantiateAttrs(TemplateArgs, EC, EnumConst); EnumConst->setAccess(Enum->getAccess()); Enum->addDecl(EnumConst); Enumerators.push_back(EnumConst); LastEnumConst = EnumConst; if (Pattern->getDeclContext()->isFunctionOrMethod() && !Enum->isScoped()) { // If the enumeration is within a function or method, record the enum // constant as a local. SemaRef.CurrentInstantiationScope->InstantiatedLocal(EC, EnumConst); } } } SemaRef.ActOnEnumBody(Enum->getLocation(), Enum->getBraceRange(), Enum, Enumerators, nullptr, nullptr); } Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { llvm_unreachable("EnumConstantDecls can only occur within EnumDecls."); } Decl * TemplateDeclInstantiator::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) { llvm_unreachable("BuiltinTemplateDecls cannot be instantiated."); } Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None); // Create a local instantiation scope for this class template, which // will contain the instantiations of the template parameters. LocalInstantiationScope Scope(SemaRef); TemplateParameterList *TempParams = D->getTemplateParameters(); TemplateParameterList *InstParams = SubstTemplateParams(TempParams); if (!InstParams) return nullptr; CXXRecordDecl *Pattern = D->getTemplatedDecl(); // Instantiate the qualifier. We have to do this first in case // we're a friend declaration, because if we are then we need to put // the new declaration in the appropriate context. NestedNameSpecifierLoc QualifierLoc = Pattern->getQualifierLoc(); if (QualifierLoc) { QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs); if (!QualifierLoc) return nullptr; } CXXRecordDecl *PrevDecl = nullptr; ClassTemplateDecl *PrevClassTemplate = nullptr; if (!isFriend && getPreviousDeclForInstantiation(Pattern)) { DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); if (!Found.empty()) { PrevClassTemplate = dyn_cast(Found.front()); if (PrevClassTemplate) PrevDecl = PrevClassTemplate->getTemplatedDecl(); } } // If this isn't a friend, then it's a member template, in which // case we just want to build the instantiation in the // specialization. If it is a friend, we want to build it in // the appropriate context. DeclContext *DC = Owner; if (isFriend) { if (QualifierLoc) { CXXScopeSpec SS; SS.Adopt(QualifierLoc); DC = SemaRef.computeDeclContext(SS); if (!DC) return nullptr; } else { DC = SemaRef.FindInstantiatedContext(Pattern->getLocation(), Pattern->getDeclContext(), TemplateArgs); } // Look for a previous declaration of the template in the owning // context. LookupResult R(SemaRef, Pattern->getDeclName(), Pattern->getLocation(), Sema::LookupOrdinaryName, Sema::ForRedeclaration); SemaRef.LookupQualifiedName(R, DC); if (R.isSingleResult()) { PrevClassTemplate = R.getAsSingle(); if (PrevClassTemplate) PrevDecl = PrevClassTemplate->getTemplatedDecl(); } if (!PrevClassTemplate && QualifierLoc) { SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope) << D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC << QualifierLoc.getSourceRange(); return nullptr; } bool AdoptedPreviousTemplateParams = false; if (PrevClassTemplate) { bool Complain = true; // HACK: libstdc++ 4.2.1 contains an ill-formed friend class // template for struct std::tr1::__detail::_Map_base, where the // template parameters of the friend declaration don't match the // template parameters of the original declaration. In this one // case, we don't complain about the ill-formed friend // declaration. if (isFriend && Pattern->getIdentifier() && Pattern->getIdentifier()->isStr("_Map_base") && DC->isNamespace() && cast(DC)->getIdentifier() && cast(DC)->getIdentifier()->isStr("__detail")) { DeclContext *DCParent = DC->getParent(); if (DCParent->isNamespace() && cast(DCParent)->getIdentifier() && cast(DCParent)->getIdentifier()->isStr("tr1")) { if (cast(DCParent)->isInStdNamespace()) Complain = false; } } TemplateParameterList *PrevParams = PrevClassTemplate->getTemplateParameters(); // Make sure the parameter lists match. if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams, Complain, Sema::TPL_TemplateMatch)) { if (Complain) return nullptr; AdoptedPreviousTemplateParams = true; InstParams = PrevParams; } // Do some additional validation, then merge default arguments // from the existing declarations. if (!AdoptedPreviousTemplateParams && SemaRef.CheckTemplateParameterList(InstParams, PrevParams, Sema::TPC_ClassTemplate)) return nullptr; } } CXXRecordDecl *RecordInst = CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), DC, Pattern->getLocStart(), Pattern->getLocation(), Pattern->getIdentifier(), PrevDecl, /*DelayTypeCreation=*/true); if (QualifierLoc) RecordInst->setQualifierInfo(QualifierLoc); ClassTemplateDecl *Inst = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams, RecordInst); assert(!(isFriend && Owner->isDependentContext())); Inst->setPreviousDecl(PrevClassTemplate); RecordInst->setDescribedClassTemplate(Inst); if (isFriend) { if (PrevClassTemplate) Inst->setAccess(PrevClassTemplate->getAccess()); else Inst->setAccess(D->getAccess()); Inst->setObjectOfFriendDecl(); // TODO: do we want to track the instantiation progeny of this // friend target decl? } else { Inst->setAccess(D->getAccess()); if (!PrevClassTemplate) Inst->setInstantiatedFromMemberTemplate(D); } // Trigger creation of the type for the instantiation. SemaRef.Context.getInjectedClassNameType(RecordInst, Inst->getInjectedClassNameSpecialization()); // Finish handling of friends. if (isFriend) { DC->makeDeclVisibleInContext(Inst); Inst->setLexicalDeclContext(Owner); RecordInst->setLexicalDeclContext(Owner); return Inst; } if (D->isOutOfLine()) { Inst->setLexicalDeclContext(D->getLexicalDeclContext()); RecordInst->setLexicalDeclContext(D->getLexicalDeclContext()); } Owner->addDecl(Inst); if (!PrevClassTemplate) { // Queue up any out-of-line partial specializations of this member // class template; the client will force their instantiation once // the enclosing class has been instantiated. SmallVector PartialSpecs; D->getPartialSpecializations(PartialSpecs); for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) if (PartialSpecs[I]->getFirstDecl()->isOutOfLine()) OutOfLinePartialSpecs.push_back(std::make_pair(Inst, PartialSpecs[I])); } return Inst; } Decl * TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D) { ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate(); // Lookup the already-instantiated declaration in the instantiation // of the class template and return that. DeclContext::lookup_result Found = Owner->lookup(ClassTemplate->getDeclName()); if (Found.empty()) return nullptr; ClassTemplateDecl *InstClassTemplate = dyn_cast(Found.front()); if (!InstClassTemplate) return nullptr; if (ClassTemplatePartialSpecializationDecl *Result = InstClassTemplate->findPartialSpecInstantiatedFromMember(D)) return Result; return InstantiateClassTemplatePartialSpecialization(InstClassTemplate, D); } Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) { assert(D->getTemplatedDecl()->isStaticDataMember() && "Only static data member templates are allowed."); // Create a local instantiation scope for this variable template, which // will contain the instantiations of the template parameters. LocalInstantiationScope Scope(SemaRef); TemplateParameterList *TempParams = D->getTemplateParameters(); TemplateParameterList *InstParams = SubstTemplateParams(TempParams); if (!InstParams) return nullptr; VarDecl *Pattern = D->getTemplatedDecl(); VarTemplateDecl *PrevVarTemplate = nullptr; if (getPreviousDeclForInstantiation(Pattern)) { DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); if (!Found.empty()) PrevVarTemplate = dyn_cast(Found.front()); } VarDecl *VarInst = cast_or_null(VisitVarDecl(Pattern, /*InstantiatingVarTemplate=*/true)); if (!VarInst) return nullptr; DeclContext *DC = Owner; VarTemplateDecl *Inst = VarTemplateDecl::Create( SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams, VarInst); VarInst->setDescribedVarTemplate(Inst); Inst->setPreviousDecl(PrevVarTemplate); Inst->setAccess(D->getAccess()); if (!PrevVarTemplate) Inst->setInstantiatedFromMemberTemplate(D); if (D->isOutOfLine()) { Inst->setLexicalDeclContext(D->getLexicalDeclContext()); VarInst->setLexicalDeclContext(D->getLexicalDeclContext()); } Owner->addDecl(Inst); if (!PrevVarTemplate) { // Queue up any out-of-line partial specializations of this member // variable template; the client will force their instantiation once // the enclosing class has been instantiated. SmallVector PartialSpecs; D->getPartialSpecializations(PartialSpecs); for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) if (PartialSpecs[I]->getFirstDecl()->isOutOfLine()) OutOfLineVarPartialSpecs.push_back( std::make_pair(Inst, PartialSpecs[I])); } return Inst; } Decl *TemplateDeclInstantiator::VisitVarTemplatePartialSpecializationDecl( VarTemplatePartialSpecializationDecl *D) { assert(D->isStaticDataMember() && "Only static data member templates are allowed."); VarTemplateDecl *VarTemplate = D->getSpecializedTemplate(); // Lookup the already-instantiated declaration and return that. DeclContext::lookup_result Found = Owner->lookup(VarTemplate->getDeclName()); assert(!Found.empty() && "Instantiation found nothing?"); VarTemplateDecl *InstVarTemplate = dyn_cast(Found.front()); assert(InstVarTemplate && "Instantiation did not find a variable template?"); if (VarTemplatePartialSpecializationDecl *Result = InstVarTemplate->findPartialSpecInstantiatedFromMember(D)) return Result; return InstantiateVarTemplatePartialSpecialization(InstVarTemplate, D); } Decl * TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { // Create a local instantiation scope for this function template, which // will contain the instantiations of the template parameters and then get // merged with the local instantiation scope for the function template // itself. LocalInstantiationScope Scope(SemaRef); TemplateParameterList *TempParams = D->getTemplateParameters(); TemplateParameterList *InstParams = SubstTemplateParams(TempParams); if (!InstParams) return nullptr; FunctionDecl *Instantiated = nullptr; if (CXXMethodDecl *DMethod = dyn_cast(D->getTemplatedDecl())) Instantiated = cast_or_null(VisitCXXMethodDecl(DMethod, InstParams)); else Instantiated = cast_or_null(VisitFunctionDecl( D->getTemplatedDecl(), InstParams)); if (!Instantiated) return nullptr; // Link the instantiated function template declaration to the function // template from which it was instantiated. FunctionTemplateDecl *InstTemplate = Instantiated->getDescribedFunctionTemplate(); InstTemplate->setAccess(D->getAccess()); assert(InstTemplate && "VisitFunctionDecl/CXXMethodDecl didn't create a template!"); bool isFriend = (InstTemplate->getFriendObjectKind() != Decl::FOK_None); // Link the instantiation back to the pattern *unless* this is a // non-definition friend declaration. if (!InstTemplate->getInstantiatedFromMemberTemplate() && !(isFriend && !D->getTemplatedDecl()->isThisDeclarationADefinition())) InstTemplate->setInstantiatedFromMemberTemplate(D); // Make declarations visible in the appropriate context. if (!isFriend) { Owner->addDecl(InstTemplate); } else if (InstTemplate->getDeclContext()->isRecord() && !getPreviousDeclForInstantiation(D)) { SemaRef.CheckFriendAccess(InstTemplate); } return InstTemplate; } Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { CXXRecordDecl *PrevDecl = nullptr; if (D->isInjectedClassName()) PrevDecl = cast(Owner); else if (CXXRecordDecl *PatternPrev = getPreviousDeclForInstantiation(D)) { NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), PatternPrev, TemplateArgs); if (!Prev) return nullptr; PrevDecl = cast(Prev); } CXXRecordDecl *Record = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner, D->getLocStart(), D->getLocation(), D->getIdentifier(), PrevDecl); // Substitute the nested name specifier, if any. if (SubstQualifier(D, Record)) return nullptr; Record->setImplicit(D->isImplicit()); // FIXME: Check against AS_none is an ugly hack to work around the issue that // the tag decls introduced by friend class declarations don't have an access // specifier. Remove once this area of the code gets sorted out. if (D->getAccess() != AS_none) Record->setAccess(D->getAccess()); if (!D->isInjectedClassName()) Record->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation); // If the original function was part of a friend declaration, // inherit its namespace state. if (D->getFriendObjectKind()) Record->setObjectOfFriendDecl(); // Make sure that anonymous structs and unions are recorded. if (D->isAnonymousStructOrUnion()) Record->setAnonymousStructOrUnion(true); if (D->isLocalClass()) SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record); // Forward the mangling number from the template to the instantiated decl. SemaRef.Context.setManglingNumber(Record, SemaRef.Context.getManglingNumber(D)); // See if the old tag was defined along with a declarator. // If it did, mark the new tag as being associated with that declarator. if (DeclaratorDecl *DD = SemaRef.Context.getDeclaratorForUnnamedTagDecl(D)) SemaRef.Context.addDeclaratorForUnnamedTagDecl(Record, DD); // See if the old tag was defined along with a typedef. // If it did, mark the new tag as being associated with that typedef. if (TypedefNameDecl *TND = SemaRef.Context.getTypedefNameForUnnamedTagDecl(D)) SemaRef.Context.addTypedefNameForUnnamedTagDecl(Record, TND); Owner->addDecl(Record); // DR1484 clarifies that the members of a local class are instantiated as part // of the instantiation of their enclosing entity. if (D->isCompleteDefinition() && D->isLocalClass()) { Sema::LocalEagerInstantiationScope LocalInstantiations(SemaRef); SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs, TSK_ImplicitInstantiation, /*Complain=*/true); // For nested local classes, we will instantiate the members when we // reach the end of the outermost (non-nested) local class. if (!D->isCXXClassMember()) SemaRef.InstantiateClassMembers(D->getLocation(), Record, TemplateArgs, TSK_ImplicitInstantiation); // This class may have local implicit instantiations that need to be // performed within this scope. LocalInstantiations.perform(); } SemaRef.DiagnoseUnusedNestedTypedefs(Record); return Record; } /// \brief Adjust the given function type for an instantiation of the /// given declaration, to cope with modifications to the function's type that /// aren't reflected in the type-source information. /// /// \param D The declaration we're instantiating. /// \param TInfo The already-instantiated type. static QualType adjustFunctionTypeForInstantiation(ASTContext &Context, FunctionDecl *D, TypeSourceInfo *TInfo) { const FunctionProtoType *OrigFunc = D->getType()->castAs(); const FunctionProtoType *NewFunc = TInfo->getType()->castAs(); if (OrigFunc->getExtInfo() == NewFunc->getExtInfo()) return TInfo->getType(); FunctionProtoType::ExtProtoInfo NewEPI = NewFunc->getExtProtoInfo(); NewEPI.ExtInfo = OrigFunc->getExtInfo(); return Context.getFunctionType(NewFunc->getReturnType(), NewFunc->getParamTypes(), NewEPI); } /// Normal class members are of more specific types and therefore /// don't make it here. This function serves two purposes: /// 1) instantiating function templates /// 2) substituting friend declarations Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, TemplateParameterList *TemplateParams) { // Check whether there is already a function template specialization for // this declaration. FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); if (FunctionTemplate && !TemplateParams) { ArrayRef Innermost = TemplateArgs.getInnermost(); void *InsertPos = nullptr; FunctionDecl *SpecFunc = FunctionTemplate->findSpecialization(Innermost, InsertPos); // If we already have a function template specialization, return it. if (SpecFunc) return SpecFunc; } bool isFriend; if (FunctionTemplate) isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None); else isFriend = (D->getFriendObjectKind() != Decl::FOK_None); bool MergeWithParentScope = (TemplateParams != nullptr) || Owner->isFunctionOrMethod() || !(isa(Owner) && cast(Owner)->isDefinedOutsideFunctionOrMethod()); LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); SmallVector Params; TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) return nullptr; QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo); NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); if (QualifierLoc) { QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs); if (!QualifierLoc) return nullptr; } // If we're instantiating a local function declaration, put the result // in the enclosing namespace; otherwise we need to find the instantiated // context. DeclContext *DC; if (D->isLocalExternDecl()) { DC = Owner; SemaRef.adjustContextForLocalExternDecl(DC); } else if (isFriend && QualifierLoc) { CXXScopeSpec SS; SS.Adopt(QualifierLoc); DC = SemaRef.computeDeclContext(SS); if (!DC) return nullptr; } else { DC = SemaRef.FindInstantiatedContext(D->getLocation(), D->getDeclContext(), TemplateArgs); } FunctionDecl *Function; if (auto *DGuide = dyn_cast(D)) Function = CXXDeductionGuideDecl::Create( SemaRef.Context, DC, D->getInnerLocStart(), DGuide->isExplicit(), D->getNameInfo(), T, TInfo, D->getSourceRange().getEnd()); else { Function = FunctionDecl::Create( SemaRef.Context, DC, D->getInnerLocStart(), D->getNameInfo(), T, TInfo, D->getCanonicalDecl()->getStorageClass(), D->isInlineSpecified(), D->hasWrittenPrototype(), D->isConstexpr()); Function->setRangeEnd(D->getSourceRange().getEnd()); } if (D->isInlined()) Function->setImplicitlyInline(); if (QualifierLoc) Function->setQualifierInfo(QualifierLoc); if (D->isLocalExternDecl()) Function->setLocalExternDecl(); DeclContext *LexicalDC = Owner; if (!isFriend && D->isOutOfLine() && !D->isLocalExternDecl()) { assert(D->getDeclContext()->isFileContext()); LexicalDC = D->getDeclContext(); } Function->setLexicalDeclContext(LexicalDC); // Attach the parameters for (unsigned P = 0; P < Params.size(); ++P) if (Params[P]) Params[P]->setOwningFunction(Function); Function->setParams(Params); SourceLocation InstantiateAtPOI; if (TemplateParams) { // Our resulting instantiation is actually a function template, since we // are substituting only the outer template parameters. For example, given // // template // struct X { // template friend void f(T, U); // }; // // X x; // // We are instantiating the friend function template "f" within X, // which means substituting int for T, but leaving "f" as a friend function // template. // Build the function template itself. FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, DC, Function->getLocation(), Function->getDeclName(), TemplateParams, Function); Function->setDescribedFunctionTemplate(FunctionTemplate); FunctionTemplate->setLexicalDeclContext(LexicalDC); if (isFriend && D->isThisDeclarationADefinition()) { FunctionTemplate->setInstantiatedFromMemberTemplate( D->getDescribedFunctionTemplate()); } } else if (FunctionTemplate) { // Record this function template specialization. ArrayRef Innermost = TemplateArgs.getInnermost(); Function->setFunctionTemplateSpecialization(FunctionTemplate, TemplateArgumentList::CreateCopy(SemaRef.Context, Innermost), /*InsertPos=*/nullptr); } else if (isFriend && D->isThisDeclarationADefinition()) { // Do not connect the friend to the template unless it's actually a // definition. We don't want non-template functions to be marked as being // template instantiations. Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); } if (InitFunctionInstantiation(Function, D)) Function->setInvalidDecl(); bool isExplicitSpecialization = false; LookupResult Previous( SemaRef, Function->getDeclName(), SourceLocation(), D->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage : Sema::LookupOrdinaryName, Sema::ForRedeclaration); if (DependentFunctionTemplateSpecializationInfo *Info = D->getDependentSpecializationInfo()) { assert(isFriend && "non-friend has dependent specialization info?"); // This needs to be set now for future sanity. Function->setObjectOfFriendDecl(); // Instantiate the explicit template arguments. TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), Info->getRAngleLoc()); if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), ExplicitArgs, TemplateArgs)) return nullptr; // Map the candidate templates to their instantiations. for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) { Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(), Info->getTemplate(I), TemplateArgs); if (!Temp) return nullptr; Previous.addDecl(cast(Temp)); } if (SemaRef.CheckFunctionTemplateSpecialization(Function, &ExplicitArgs, Previous)) Function->setInvalidDecl(); isExplicitSpecialization = true; } else if (TemplateParams || !FunctionTemplate) { // Look only into the namespace where the friend would be declared to // find a previous declaration. This is the innermost enclosing namespace, // as described in ActOnFriendFunctionDecl. SemaRef.LookupQualifiedName(Previous, DC); // In C++, the previous declaration we find might be a tag type // (class or enum). In this case, the new declaration will hide the // tag type. Note that this does does not apply if we're declaring a // typedef (C++ [dcl.typedef]p4). if (Previous.isSingleTagDecl()) Previous.clear(); } if (isFriend) Function->setObjectOfFriendDecl(); SemaRef.CheckFunctionDeclaration(/*Scope*/ nullptr, Function, Previous, isExplicitSpecialization); NamedDecl *PrincipalDecl = (TemplateParams ? cast(FunctionTemplate) : Function); // If the original function was part of a friend declaration, // inherit its namespace state and add it to the owner. if (isFriend) { PrincipalDecl->setObjectOfFriendDecl(); DC->makeDeclVisibleInContext(PrincipalDecl); bool QueuedInstantiation = false; // C++11 [temp.friend]p4 (DR329): // When a function is defined in a friend function declaration in a class // template, the function is instantiated when the function is odr-used. // The same restrictions on multiple declarations and definitions that // apply to non-template function declarations and definitions also apply // to these implicit definitions. if (D->isThisDeclarationADefinition()) { // Check for a function body. const FunctionDecl *Definition = nullptr; if (Function->isDefined(Definition) && Definition->getTemplateSpecializationKind() == TSK_Undeclared) { SemaRef.Diag(Function->getLocation(), diag::err_redefinition) << Function->getDeclName(); SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition); } // Check for redefinitions due to other instantiations of this or // a similar friend function. else for (auto R : Function->redecls()) { if (R == Function) continue; // If some prior declaration of this function has been used, we need // to instantiate its definition. if (!QueuedInstantiation && R->isUsed(false)) { if (MemberSpecializationInfo *MSInfo = Function->getMemberSpecializationInfo()) { if (MSInfo->getPointOfInstantiation().isInvalid()) { SourceLocation Loc = R->getLocation(); // FIXME MSInfo->setPointOfInstantiation(Loc); SemaRef.PendingLocalImplicitInstantiations.push_back( std::make_pair(Function, Loc)); QueuedInstantiation = true; } } } // If some prior declaration of this function was a friend with an // uninstantiated definition, reject it. if (R->getFriendObjectKind()) { if (const FunctionDecl *RPattern = R->getTemplateInstantiationPattern()) { if (RPattern->isDefined(RPattern)) { SemaRef.Diag(Function->getLocation(), diag::err_redefinition) << Function->getDeclName(); SemaRef.Diag(R->getLocation(), diag::note_previous_definition); break; } } } } } // Check the template parameter list against the previous declaration. The // goal here is to pick up default arguments added since the friend was // declared; we know the template parameter lists match, since otherwise // we would not have picked this template as the previous declaration. if (TemplateParams && FunctionTemplate->getPreviousDecl()) { SemaRef.CheckTemplateParameterList( TemplateParams, FunctionTemplate->getPreviousDecl()->getTemplateParameters(), Function->isThisDeclarationADefinition() ? Sema::TPC_FriendFunctionTemplateDefinition : Sema::TPC_FriendFunctionTemplate); } } if (Function->isLocalExternDecl() && !Function->getPreviousDecl()) DC->makeDeclVisibleInContext(PrincipalDecl); if (Function->isOverloadedOperator() && !DC->isRecord() && PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) PrincipalDecl->setNonMemberOperator(); assert(!D->isDefaulted() && "only methods should be defaulted"); return Function; } Decl * TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, TemplateParameterList *TemplateParams, bool IsClassScopeSpecialization) { FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); if (FunctionTemplate && !TemplateParams) { // We are creating a function template specialization from a function // template. Check whether there is already a function template // specialization for this particular set of template arguments. ArrayRef Innermost = TemplateArgs.getInnermost(); void *InsertPos = nullptr; FunctionDecl *SpecFunc = FunctionTemplate->findSpecialization(Innermost, InsertPos); // If we already have a function template specialization, return it. if (SpecFunc) return SpecFunc; } bool isFriend; if (FunctionTemplate) isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None); else isFriend = (D->getFriendObjectKind() != Decl::FOK_None); bool MergeWithParentScope = (TemplateParams != nullptr) || !(isa(Owner) && cast(Owner)->isDefinedOutsideFunctionOrMethod()); LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); // Instantiate enclosing template arguments for friends. SmallVector TempParamLists; unsigned NumTempParamLists = 0; if (isFriend && (NumTempParamLists = D->getNumTemplateParameterLists())) { TempParamLists.resize(NumTempParamLists); for (unsigned I = 0; I != NumTempParamLists; ++I) { TemplateParameterList *TempParams = D->getTemplateParameterList(I); TemplateParameterList *InstParams = SubstTemplateParams(TempParams); if (!InstParams) return nullptr; TempParamLists[I] = InstParams; } } SmallVector Params; TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) return nullptr; QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo); NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); if (QualifierLoc) { QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs); if (!QualifierLoc) return nullptr; } DeclContext *DC = Owner; if (isFriend) { if (QualifierLoc) { CXXScopeSpec SS; SS.Adopt(QualifierLoc); DC = SemaRef.computeDeclContext(SS); if (DC && SemaRef.RequireCompleteDeclContext(SS, DC)) return nullptr; } else { DC = SemaRef.FindInstantiatedContext(D->getLocation(), D->getDeclContext(), TemplateArgs); } if (!DC) return nullptr; } // Build the instantiated method declaration. CXXRecordDecl *Record = cast(DC); CXXMethodDecl *Method = nullptr; SourceLocation StartLoc = D->getInnerLocStart(); DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); if (CXXConstructorDecl *Constructor = dyn_cast(D)) { Method = CXXConstructorDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, Constructor->isExplicit(), Constructor->isInlineSpecified(), false, Constructor->isConstexpr()); Method->setRangeEnd(Constructor->getLocEnd()); } else if (CXXDestructorDecl *Destructor = dyn_cast(D)) { Method = CXXDestructorDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, Destructor->isInlineSpecified(), false); Method->setRangeEnd(Destructor->getLocEnd()); } else if (CXXConversionDecl *Conversion = dyn_cast(D)) { Method = CXXConversionDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, Conversion->isInlineSpecified(), Conversion->isExplicit(), Conversion->isConstexpr(), Conversion->getLocEnd()); } else { StorageClass SC = D->isStatic() ? SC_Static : SC_None; Method = CXXMethodDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, SC, D->isInlineSpecified(), D->isConstexpr(), D->getLocEnd()); } if (D->isInlined()) Method->setImplicitlyInline(); if (QualifierLoc) Method->setQualifierInfo(QualifierLoc); if (TemplateParams) { // Our resulting instantiation is actually a function template, since we // are substituting only the outer template parameters. For example, given // // template // struct X { // template void f(T, U); // }; // // X x; // // We are instantiating the member template "f" within X, which means // substituting int for T, but leaving "f" as a member function template. // Build the function template itself. FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, Record, Method->getLocation(), Method->getDeclName(), TemplateParams, Method); if (isFriend) { FunctionTemplate->setLexicalDeclContext(Owner); FunctionTemplate->setObjectOfFriendDecl(); } else if (D->isOutOfLine()) FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext()); Method->setDescribedFunctionTemplate(FunctionTemplate); } else if (FunctionTemplate) { // Record this function template specialization. ArrayRef Innermost = TemplateArgs.getInnermost(); Method->setFunctionTemplateSpecialization(FunctionTemplate, TemplateArgumentList::CreateCopy(SemaRef.Context, Innermost), /*InsertPos=*/nullptr); } else if (!isFriend) { // Record that this is an instantiation of a member function. Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); } // If we are instantiating a member function defined // out-of-line, the instantiation will have the same lexical // context (which will be a namespace scope) as the template. if (isFriend) { if (NumTempParamLists) Method->setTemplateParameterListsInfo( SemaRef.Context, llvm::makeArrayRef(TempParamLists.data(), NumTempParamLists)); Method->setLexicalDeclContext(Owner); Method->setObjectOfFriendDecl(); } else if (D->isOutOfLine()) Method->setLexicalDeclContext(D->getLexicalDeclContext()); // Attach the parameters for (unsigned P = 0; P < Params.size(); ++P) Params[P]->setOwningFunction(Method); Method->setParams(Params); if (InitMethodInstantiation(Method, D)) Method->setInvalidDecl(); LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName, Sema::ForRedeclaration); if (!FunctionTemplate || TemplateParams || isFriend) { SemaRef.LookupQualifiedName(Previous, Record); // In C++, the previous declaration we find might be a tag type // (class or enum). In this case, the new declaration will hide the // tag type. Note that this does does not apply if we're declaring a // typedef (C++ [dcl.typedef]p4). if (Previous.isSingleTagDecl()) Previous.clear(); } if (!IsClassScopeSpecialization) SemaRef.CheckFunctionDeclaration(nullptr, Method, Previous, false); if (D->isPure()) SemaRef.CheckPureMethod(Method, SourceRange()); // Propagate access. For a non-friend declaration, the access is // whatever we're propagating from. For a friend, it should be the // previous declaration we just found. if (isFriend && Method->getPreviousDecl()) Method->setAccess(Method->getPreviousDecl()->getAccess()); else Method->setAccess(D->getAccess()); if (FunctionTemplate) FunctionTemplate->setAccess(Method->getAccess()); SemaRef.CheckOverrideControl(Method); // If a function is defined as defaulted or deleted, mark it as such now. if (D->isExplicitlyDefaulted()) SemaRef.SetDeclDefaulted(Method, Method->getLocation()); if (D->isDeletedAsWritten()) SemaRef.SetDeclDeleted(Method, Method->getLocation()); // If there's a function template, let our caller handle it. if (FunctionTemplate) { // do nothing // Don't hide a (potentially) valid declaration with an invalid one. } else if (Method->isInvalidDecl() && !Previous.empty()) { // do nothing // Otherwise, check access to friends and make them visible. } else if (isFriend) { // We only need to re-check access for methods which we didn't // manage to match during parsing. if (!D->getPreviousDecl()) SemaRef.CheckFriendAccess(Method); Record->makeDeclVisibleInContext(Method); // Otherwise, add the declaration. We don't need to do this for // class-scope specializations because we'll have matched them with // the appropriate template. } else if (!IsClassScopeSpecialization) { Owner->addDecl(Method); } return Method; } Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) { return VisitCXXMethodDecl(D); } Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) { return VisitCXXMethodDecl(D); } Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { return VisitCXXMethodDecl(D); } Decl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, None, /*ExpectParameterPack=*/ false); } Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( TemplateTypeParmDecl *D) { // TODO: don't always clone when decls are refcounted. assert(D->getTypeForDecl()->isTemplateTypeParmType()); TemplateTypeParmDecl *Inst = TemplateTypeParmDecl::Create( SemaRef.Context, Owner, D->getLocStart(), D->getLocation(), D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), D->getIndex(), D->getIdentifier(), D->wasDeclaredWithTypename(), D->isParameterPack()); Inst->setAccess(AS_public); if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { TypeSourceInfo *InstantiatedDefaultArg = SemaRef.SubstType(D->getDefaultArgumentInfo(), TemplateArgs, D->getDefaultArgumentLoc(), D->getDeclName()); if (InstantiatedDefaultArg) Inst->setDefaultArgument(InstantiatedDefaultArg); } // Introduce this template parameter's instantiation into the instantiation // scope. SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Inst); return Inst; } Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( NonTypeTemplateParmDecl *D) { // Substitute into the type of the non-type template parameter. TypeLoc TL = D->getTypeSourceInfo()->getTypeLoc(); SmallVector ExpandedParameterPackTypesAsWritten; SmallVector ExpandedParameterPackTypes; bool IsExpandedParameterPack = false; TypeSourceInfo *DI; QualType T; bool Invalid = false; if (D->isExpandedParameterPack()) { // The non-type template parameter pack is an already-expanded pack // expansion of types. Substitute into each of the expanded types. ExpandedParameterPackTypes.reserve(D->getNumExpansionTypes()); ExpandedParameterPackTypesAsWritten.reserve(D->getNumExpansionTypes()); for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) { TypeSourceInfo *NewDI = SemaRef.SubstType(D->getExpansionTypeSourceInfo(I), TemplateArgs, D->getLocation(), D->getDeclName()); if (!NewDI) return nullptr; QualType NewT = SemaRef.CheckNonTypeTemplateParameterType(NewDI, D->getLocation()); if (NewT.isNull()) return nullptr; ExpandedParameterPackTypesAsWritten.push_back(NewDI); ExpandedParameterPackTypes.push_back(NewT); } IsExpandedParameterPack = true; DI = D->getTypeSourceInfo(); T = DI->getType(); } else if (D->isPackExpansion()) { // The non-type template parameter pack's type is a pack expansion of types. // Determine whether we need to expand this parameter pack into separate // types. PackExpansionTypeLoc Expansion = TL.castAs(); TypeLoc Pattern = Expansion.getPatternLoc(); SmallVector Unexpanded; SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded); // Determine whether the set of unexpanded parameter packs can and should // be expanded. bool Expand = true; bool RetainExpansion = false; Optional OrigNumExpansions = Expansion.getTypePtr()->getNumExpansions(); Optional NumExpansions = OrigNumExpansions; if (SemaRef.CheckParameterPacksForExpansion(Expansion.getEllipsisLoc(), Pattern.getSourceRange(), Unexpanded, TemplateArgs, Expand, RetainExpansion, NumExpansions)) return nullptr; if (Expand) { for (unsigned I = 0; I != *NumExpansions; ++I) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); TypeSourceInfo *NewDI = SemaRef.SubstType(Pattern, TemplateArgs, D->getLocation(), D->getDeclName()); if (!NewDI) return nullptr; QualType NewT = SemaRef.CheckNonTypeTemplateParameterType(NewDI, D->getLocation()); if (NewT.isNull()) return nullptr; ExpandedParameterPackTypesAsWritten.push_back(NewDI); ExpandedParameterPackTypes.push_back(NewT); } // Note that we have an expanded parameter pack. The "type" of this // expanded parameter pack is the original expansion type, but callers // will end up using the expanded parameter pack types for type-checking. IsExpandedParameterPack = true; DI = D->getTypeSourceInfo(); T = DI->getType(); } else { // We cannot fully expand the pack expansion now, so substitute into the // pattern and create a new pack expansion type. Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1); TypeSourceInfo *NewPattern = SemaRef.SubstType(Pattern, TemplateArgs, D->getLocation(), D->getDeclName()); if (!NewPattern) return nullptr; SemaRef.CheckNonTypeTemplateParameterType(NewPattern, D->getLocation()); DI = SemaRef.CheckPackExpansion(NewPattern, Expansion.getEllipsisLoc(), NumExpansions); if (!DI) return nullptr; T = DI->getType(); } } else { // Simple case: substitution into a parameter that is not a parameter pack. DI = SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs, D->getLocation(), D->getDeclName()); if (!DI) return nullptr; // Check that this type is acceptable for a non-type template parameter. T = SemaRef.CheckNonTypeTemplateParameterType(DI, D->getLocation()); if (T.isNull()) { T = SemaRef.Context.IntTy; Invalid = true; } } NonTypeTemplateParmDecl *Param; if (IsExpandedParameterPack) Param = NonTypeTemplateParmDecl::Create( SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), D->getPosition(), D->getIdentifier(), T, DI, ExpandedParameterPackTypes, ExpandedParameterPackTypesAsWritten); else Param = NonTypeTemplateParmDecl::Create( SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), D->getPosition(), D->getIdentifier(), T, D->isParameterPack(), DI); Param->setAccess(AS_public); if (Invalid) Param->setInvalidDecl(); if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { EnterExpressionEvaluationContext ConstantEvaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); ExprResult Value = SemaRef.SubstExpr(D->getDefaultArgument(), TemplateArgs); if (!Value.isInvalid()) Param->setDefaultArgument(Value.get()); } // Introduce this template parameter's instantiation into the instantiation // scope. SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param); return Param; } static void collectUnexpandedParameterPacks( Sema &S, TemplateParameterList *Params, SmallVectorImpl &Unexpanded) { for (const auto &P : *Params) { if (P->isTemplateParameterPack()) continue; if (NonTypeTemplateParmDecl *NTTP = dyn_cast(P)) S.collectUnexpandedParameterPacks(NTTP->getTypeSourceInfo()->getTypeLoc(), Unexpanded); if (TemplateTemplateParmDecl *TTP = dyn_cast(P)) collectUnexpandedParameterPacks(S, TTP->getTemplateParameters(), Unexpanded); } } Decl * TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( TemplateTemplateParmDecl *D) { // Instantiate the template parameter list of the template template parameter. TemplateParameterList *TempParams = D->getTemplateParameters(); TemplateParameterList *InstParams; SmallVector ExpandedParams; bool IsExpandedParameterPack = false; if (D->isExpandedParameterPack()) { // The template template parameter pack is an already-expanded pack // expansion of template parameters. Substitute into each of the expanded // parameters. ExpandedParams.reserve(D->getNumExpansionTemplateParameters()); for (unsigned I = 0, N = D->getNumExpansionTemplateParameters(); I != N; ++I) { LocalInstantiationScope Scope(SemaRef); TemplateParameterList *Expansion = SubstTemplateParams(D->getExpansionTemplateParameters(I)); if (!Expansion) return nullptr; ExpandedParams.push_back(Expansion); } IsExpandedParameterPack = true; InstParams = TempParams; } else if (D->isPackExpansion()) { // The template template parameter pack expands to a pack of template // template parameters. Determine whether we need to expand this parameter // pack into separate parameters. SmallVector Unexpanded; collectUnexpandedParameterPacks(SemaRef, D->getTemplateParameters(), Unexpanded); // Determine whether the set of unexpanded parameter packs can and should // be expanded. bool Expand = true; bool RetainExpansion = false; Optional NumExpansions; if (SemaRef.CheckParameterPacksForExpansion(D->getLocation(), TempParams->getSourceRange(), Unexpanded, TemplateArgs, Expand, RetainExpansion, NumExpansions)) return nullptr; if (Expand) { for (unsigned I = 0; I != *NumExpansions; ++I) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); LocalInstantiationScope Scope(SemaRef); TemplateParameterList *Expansion = SubstTemplateParams(TempParams); if (!Expansion) return nullptr; ExpandedParams.push_back(Expansion); } // Note that we have an expanded parameter pack. The "type" of this // expanded parameter pack is the original expansion type, but callers // will end up using the expanded parameter pack types for type-checking. IsExpandedParameterPack = true; InstParams = TempParams; } else { // We cannot fully expand the pack expansion now, so just substitute // into the pattern. Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1); LocalInstantiationScope Scope(SemaRef); InstParams = SubstTemplateParams(TempParams); if (!InstParams) return nullptr; } } else { // Perform the actual substitution of template parameters within a new, // local instantiation scope. LocalInstantiationScope Scope(SemaRef); InstParams = SubstTemplateParams(TempParams); if (!InstParams) return nullptr; } // Build the template template parameter. TemplateTemplateParmDecl *Param; if (IsExpandedParameterPack) Param = TemplateTemplateParmDecl::Create( SemaRef.Context, Owner, D->getLocation(), D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), D->getPosition(), D->getIdentifier(), InstParams, ExpandedParams); else Param = TemplateTemplateParmDecl::Create( SemaRef.Context, Owner, D->getLocation(), D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), D->getPosition(), D->isParameterPack(), D->getIdentifier(), InstParams); if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { NestedNameSpecifierLoc QualifierLoc = D->getDefaultArgument().getTemplateQualifierLoc(); QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs); TemplateName TName = SemaRef.SubstTemplateName( QualifierLoc, D->getDefaultArgument().getArgument().getAsTemplate(), D->getDefaultArgument().getTemplateNameLoc(), TemplateArgs); if (!TName.isNull()) Param->setDefaultArgument( SemaRef.Context, TemplateArgumentLoc(TemplateArgument(TName), D->getDefaultArgument().getTemplateQualifierLoc(), D->getDefaultArgument().getTemplateNameLoc())); } Param->setAccess(AS_public); // Introduce this template parameter's instantiation into the instantiation // scope. SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param); return Param; } Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { // Using directives are never dependent (and never contain any types or // expressions), so they require no explicit instantiation work. UsingDirectiveDecl *Inst = UsingDirectiveDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getNamespaceKeyLocation(), D->getQualifierLoc(), D->getIdentLocation(), D->getNominatedNamespace(), D->getCommonAncestor()); // Add the using directive to its declaration context // only if this is not a function or method. if (!Owner->isFunctionOrMethod()) Owner->addDecl(Inst); return Inst; } Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { // The nested name specifier may be dependent, for example // template struct t { // struct s1 { T f1(); }; // struct s2 : s1 { using s1::f1; }; // }; // template struct t; // Here, in using s1::f1, s1 refers to t::s1; // we need to substitute for t::s1. NestedNameSpecifierLoc QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), TemplateArgs); if (!QualifierLoc) return nullptr; // For an inheriting constructor declaration, the name of the using // declaration is the name of a constructor in this class, not in the // base class. DeclarationNameInfo NameInfo = D->getNameInfo(); if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) if (auto *RD = dyn_cast(SemaRef.CurContext)) NameInfo.setName(SemaRef.Context.DeclarationNames.getCXXConstructorName( SemaRef.Context.getCanonicalType(SemaRef.Context.getRecordType(RD)))); // We only need to do redeclaration lookups if we're in a class // scope (in fact, it's not really even possible in non-class // scopes). bool CheckRedeclaration = Owner->isRecord(); LookupResult Prev(SemaRef, NameInfo, Sema::LookupUsingDeclName, Sema::ForRedeclaration); UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner, D->getUsingLoc(), QualifierLoc, NameInfo, D->hasTypename()); CXXScopeSpec SS; SS.Adopt(QualifierLoc); if (CheckRedeclaration) { Prev.setHideTags(false); SemaRef.LookupQualifiedName(Prev, Owner); // Check for invalid redeclarations. if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLoc(), D->hasTypename(), SS, D->getLocation(), Prev)) NewUD->setInvalidDecl(); } if (!NewUD->isInvalidDecl() && SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), D->hasTypename(), SS, NameInfo, D->getLocation())) NewUD->setInvalidDecl(); SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D); NewUD->setAccess(D->getAccess()); Owner->addDecl(NewUD); // Don't process the shadow decls for an invalid decl. if (NewUD->isInvalidDecl()) return NewUD; if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) SemaRef.CheckInheritingConstructorUsingDecl(NewUD); bool isFunctionScope = Owner->isFunctionOrMethod(); // Process the shadow decls. for (auto *Shadow : D->shadows()) { // FIXME: UsingShadowDecl doesn't preserve its immediate target, so // reconstruct it in the case where it matters. NamedDecl *OldTarget = Shadow->getTargetDecl(); if (auto *CUSD = dyn_cast(Shadow)) if (auto *BaseShadow = CUSD->getNominatedBaseClassShadowDecl()) OldTarget = BaseShadow; NamedDecl *InstTarget = cast_or_null(SemaRef.FindInstantiatedDecl( Shadow->getLocation(), OldTarget, TemplateArgs)); if (!InstTarget) return nullptr; UsingShadowDecl *PrevDecl = nullptr; if (CheckRedeclaration) { if (SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev, PrevDecl)) continue; } else if (UsingShadowDecl *OldPrev = getPreviousDeclForInstantiation(Shadow)) { PrevDecl = cast_or_null(SemaRef.FindInstantiatedDecl( Shadow->getLocation(), OldPrev, TemplateArgs)); } UsingShadowDecl *InstShadow = SemaRef.BuildUsingShadowDecl(/*Scope*/nullptr, NewUD, InstTarget, PrevDecl); SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow); if (isFunctionScope) SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow); } return NewUD; } Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) { // Ignore these; we handle them in bulk when processing the UsingDecl. return nullptr; } Decl *TemplateDeclInstantiator::VisitConstructorUsingShadowDecl( ConstructorUsingShadowDecl *D) { // Ignore these; we handle them in bulk when processing the UsingDecl. return nullptr; } template Decl *TemplateDeclInstantiator::instantiateUnresolvedUsingDecl( T *D, bool InstantiatingPackElement) { // If this is a pack expansion, expand it now. if (D->isPackExpansion() && !InstantiatingPackElement) { SmallVector Unexpanded; SemaRef.collectUnexpandedParameterPacks(D->getQualifierLoc(), Unexpanded); SemaRef.collectUnexpandedParameterPacks(D->getNameInfo(), Unexpanded); // Determine whether the set of unexpanded parameter packs can and should // be expanded. bool Expand = true; bool RetainExpansion = false; Optional NumExpansions; if (SemaRef.CheckParameterPacksForExpansion( D->getEllipsisLoc(), D->getSourceRange(), Unexpanded, TemplateArgs, Expand, RetainExpansion, NumExpansions)) return nullptr; // This declaration cannot appear within a function template signature, // so we can't have a partial argument list for a parameter pack. assert(!RetainExpansion && "should never need to retain an expansion for UsingPackDecl"); if (!Expand) { // We cannot fully expand the pack expansion now, so substitute into the // pattern and create a new pack expansion. Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1); return instantiateUnresolvedUsingDecl(D, true); } // Within a function, we don't have any normal way to check for conflicts // between shadow declarations from different using declarations in the // same pack expansion, but this is always ill-formed because all expansions // must produce (conflicting) enumerators. // // Sadly we can't just reject this in the template definition because it // could be valid if the pack is empty or has exactly one expansion. if (D->getDeclContext()->isFunctionOrMethod() && *NumExpansions > 1) { SemaRef.Diag(D->getEllipsisLoc(), diag::err_using_decl_redeclaration_expansion); return nullptr; } // Instantiate the slices of this pack and build a UsingPackDecl. SmallVector Expansions; for (unsigned I = 0; I != *NumExpansions; ++I) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); Decl *Slice = instantiateUnresolvedUsingDecl(D, true); if (!Slice) return nullptr; // Note that we can still get unresolved using declarations here, if we // had arguments for all packs but the pattern also contained other // template arguments (this only happens during partial substitution, eg // into the body of a generic lambda in a function template). Expansions.push_back(cast(Slice)); } auto *NewD = SemaRef.BuildUsingPackDecl(D, Expansions); if (isDeclWithinFunction(D)) SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewD); return NewD; } UnresolvedUsingTypenameDecl *TD = dyn_cast(D); SourceLocation TypenameLoc = TD ? TD->getTypenameLoc() : SourceLocation(); NestedNameSpecifierLoc QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), TemplateArgs); if (!QualifierLoc) return nullptr; CXXScopeSpec SS; SS.Adopt(QualifierLoc); DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); // Produce a pack expansion only if we're not instantiating a particular // slice of a pack expansion. bool InstantiatingSlice = D->getEllipsisLoc().isValid() && SemaRef.ArgumentPackSubstitutionIndex != -1; SourceLocation EllipsisLoc = InstantiatingSlice ? SourceLocation() : D->getEllipsisLoc(); NamedDecl *UD = SemaRef.BuildUsingDeclaration( /*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(), /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, nullptr, /*IsInstantiation*/ true); if (UD) SemaRef.Context.setInstantiatedFromUsingDecl(UD, D); return UD; } Decl *TemplateDeclInstantiator::VisitUnresolvedUsingTypenameDecl( UnresolvedUsingTypenameDecl *D) { return instantiateUnresolvedUsingDecl(D); } Decl *TemplateDeclInstantiator::VisitUnresolvedUsingValueDecl( UnresolvedUsingValueDecl *D) { return instantiateUnresolvedUsingDecl(D); } Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) { SmallVector Expansions; for (auto *UD : D->expansions()) { if (auto *NewUD = SemaRef.FindInstantiatedDecl(D->getLocation(), UD, TemplateArgs)) Expansions.push_back(cast(NewUD)); else return nullptr; } auto *NewD = SemaRef.BuildUsingPackDecl(D, Expansions); if (isDeclWithinFunction(D)) SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewD); return NewD; } Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl( ClassScopeFunctionSpecializationDecl *Decl) { CXXMethodDecl *OldFD = Decl->getSpecialization(); CXXMethodDecl *NewFD = cast_or_null(VisitCXXMethodDecl(OldFD, nullptr, true)); if (!NewFD) return nullptr; LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName, Sema::ForRedeclaration); TemplateArgumentListInfo TemplateArgs; TemplateArgumentListInfo *TemplateArgsPtr = nullptr; if (Decl->hasExplicitTemplateArgs()) { TemplateArgs = Decl->templateArgs(); TemplateArgsPtr = &TemplateArgs; } SemaRef.LookupQualifiedName(Previous, SemaRef.CurContext); if (SemaRef.CheckFunctionTemplateSpecialization(NewFD, TemplateArgsPtr, Previous)) { NewFD->setInvalidDecl(); return NewFD; } // Associate the specialization with the pattern. FunctionDecl *Specialization = cast(Previous.getFoundDecl()); assert(Specialization && "Class scope Specialization is null"); SemaRef.Context.setClassScopeSpecializationPattern(Specialization, OldFD); return NewFD; } Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl( OMPThreadPrivateDecl *D) { SmallVector Vars; for (auto *I : D->varlists()) { Expr *Var = SemaRef.SubstExpr(I, TemplateArgs).get(); assert(isa(Var) && "threadprivate arg is not a DeclRefExpr"); Vars.push_back(Var); } OMPThreadPrivateDecl *TD = SemaRef.CheckOMPThreadPrivateDecl(D->getLocation(), Vars); TD->setAccess(AS_public); Owner->addDecl(TD); return TD; } Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl( OMPDeclareReductionDecl *D) { // Instantiate type and check if it is allowed. QualType SubstReductionType = SemaRef.ActOnOpenMPDeclareReductionType( D->getLocation(), ParsedType::make(SemaRef.SubstType(D->getType(), TemplateArgs, D->getLocation(), DeclarationName()))); if (SubstReductionType.isNull()) return nullptr; bool IsCorrect = !SubstReductionType.isNull(); // Create instantiated copy. std::pair ReductionTypes[] = { std::make_pair(SubstReductionType, D->getLocation())}; auto *PrevDeclInScope = D->getPrevDeclInScope(); if (PrevDeclInScope && !PrevDeclInScope->isInvalidDecl()) { PrevDeclInScope = cast( SemaRef.CurrentInstantiationScope->findInstantiationOf(PrevDeclInScope) ->get()); } auto DRD = SemaRef.ActOnOpenMPDeclareReductionDirectiveStart( /*S=*/nullptr, Owner, D->getDeclName(), ReductionTypes, D->getAccess(), PrevDeclInScope); auto *NewDRD = cast(DRD.get().getSingleDecl()); if (isDeclWithinFunction(NewDRD)) SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDRD); Expr *SubstCombiner = nullptr; Expr *SubstInitializer = nullptr; // Combiners instantiation sequence. if (D->getCombiner()) { SemaRef.ActOnOpenMPDeclareReductionCombinerStart( /*S=*/nullptr, NewDRD); const char *Names[] = {"omp_in", "omp_out"}; for (auto &Name : Names) { DeclarationName DN(&SemaRef.Context.Idents.get(Name)); auto OldLookup = D->lookup(DN); auto Lookup = NewDRD->lookup(DN); if (!OldLookup.empty() && !Lookup.empty()) { assert(Lookup.size() == 1 && OldLookup.size() == 1); SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldLookup.front(), Lookup.front()); } } SubstCombiner = SemaRef.SubstExpr(D->getCombiner(), TemplateArgs).get(); SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner); // Initializers instantiation sequence. if (D->getInitializer()) { SemaRef.ActOnOpenMPDeclareReductionInitializerStart( /*S=*/nullptr, NewDRD); const char *Names[] = {"omp_orig", "omp_priv"}; for (auto &Name : Names) { DeclarationName DN(&SemaRef.Context.Idents.get(Name)); auto OldLookup = D->lookup(DN); auto Lookup = NewDRD->lookup(DN); if (!OldLookup.empty() && !Lookup.empty()) { assert(Lookup.size() == 1 && OldLookup.size() == 1); SemaRef.CurrentInstantiationScope->InstantiatedLocal( OldLookup.front(), Lookup.front()); } } SubstInitializer = SemaRef.SubstExpr(D->getInitializer(), TemplateArgs).get(); SemaRef.ActOnOpenMPDeclareReductionInitializerEnd(NewDRD, SubstInitializer); } IsCorrect = IsCorrect && SubstCombiner && (!D->getInitializer() || SubstInitializer); } else IsCorrect = false; (void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd(/*S=*/nullptr, DRD, IsCorrect); return NewDRD; } Decl *TemplateDeclInstantiator::VisitOMPCapturedExprDecl( OMPCapturedExprDecl * /*D*/) { llvm_unreachable("Should not be met in templates"); } Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) { return VisitFunctionDecl(D, nullptr); } Decl * TemplateDeclInstantiator::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { return VisitFunctionDecl(D, nullptr); } Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) { return VisitCXXMethodDecl(D, nullptr); } Decl *TemplateDeclInstantiator::VisitRecordDecl(RecordDecl *D) { llvm_unreachable("There are only CXXRecordDecls in C++"); } Decl * TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl *D) { // As a MS extension, we permit class-scope explicit specialization // of member class templates. ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate(); assert(ClassTemplate->getDeclContext()->isRecord() && D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization && "can only instantiate an explicit specialization " "for a member class template"); // Lookup the already-instantiated declaration in the instantiation // of the class template. FIXME: Diagnose or assert if this fails? DeclContext::lookup_result Found = Owner->lookup(ClassTemplate->getDeclName()); if (Found.empty()) return nullptr; ClassTemplateDecl *InstClassTemplate = dyn_cast(Found.front()); if (!InstClassTemplate) return nullptr; // Substitute into the template arguments of the class template explicit // specialization. TemplateSpecializationTypeLoc Loc = D->getTypeAsWritten()->getTypeLoc(). castAs(); TemplateArgumentListInfo InstTemplateArgs(Loc.getLAngleLoc(), Loc.getRAngleLoc()); SmallVector ArgLocs; for (unsigned I = 0; I != Loc.getNumArgs(); ++I) ArgLocs.push_back(Loc.getArgLoc(I)); if (SemaRef.Subst(ArgLocs.data(), ArgLocs.size(), InstTemplateArgs, TemplateArgs)) return nullptr; // Check that the template argument list is well-formed for this // class template. SmallVector Converted; if (SemaRef.CheckTemplateArgumentList(InstClassTemplate, D->getLocation(), InstTemplateArgs, false, Converted)) return nullptr; // Figure out where to insert this class template explicit specialization // in the member template's set of class template explicit specializations. void *InsertPos = nullptr; ClassTemplateSpecializationDecl *PrevDecl = InstClassTemplate->findSpecialization(Converted, InsertPos); // Check whether we've already seen a conflicting instantiation of this // declaration (for instance, if there was a prior implicit instantiation). bool Ignored; if (PrevDecl && SemaRef.CheckSpecializationInstantiationRedecl(D->getLocation(), D->getSpecializationKind(), PrevDecl, PrevDecl->getSpecializationKind(), PrevDecl->getPointOfInstantiation(), Ignored)) return nullptr; // If PrevDecl was a definition and D is also a definition, diagnose. // This happens in cases like: // // template // struct Outer { // template struct Inner; // template<> struct Inner {}; // template<> struct Inner {}; // }; // // Outer outer; // error: the explicit specializations of Inner // // have the same signature. if (PrevDecl && PrevDecl->getDefinition() && D->isThisDeclarationADefinition()) { SemaRef.Diag(D->getLocation(), diag::err_redefinition) << PrevDecl; SemaRef.Diag(PrevDecl->getDefinition()->getLocation(), diag::note_previous_definition); return nullptr; } // Create the class template partial specialization declaration. ClassTemplateSpecializationDecl *InstD = ClassTemplateSpecializationDecl::Create(SemaRef.Context, D->getTagKind(), Owner, D->getLocStart(), D->getLocation(), InstClassTemplate, Converted, PrevDecl); // Add this partial specialization to the set of class template partial // specializations. if (!PrevDecl) InstClassTemplate->AddSpecialization(InstD, InsertPos); // Substitute the nested name specifier, if any. if (SubstQualifier(D, InstD)) return nullptr; // Build the canonical type that describes the converted template // arguments of the class template explicit specialization. QualType CanonType = SemaRef.Context.getTemplateSpecializationType( TemplateName(InstClassTemplate), Converted, SemaRef.Context.getRecordType(InstD)); // Build the fully-sugared type for this class template // specialization as the user wrote in the specialization // itself. This means that we'll pretty-print the type retrieved // from the specialization's declaration the way that the user // actually wrote the specialization, rather than formatting the // name based on the "canonical" representation used to store the // template arguments in the specialization. TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo( TemplateName(InstClassTemplate), D->getLocation(), InstTemplateArgs, CanonType); InstD->setAccess(D->getAccess()); InstD->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation); InstD->setSpecializationKind(D->getSpecializationKind()); InstD->setTypeAsWritten(WrittenTy); InstD->setExternLoc(D->getExternLoc()); InstD->setTemplateKeywordLoc(D->getTemplateKeywordLoc()); Owner->addDecl(InstD); // Instantiate the members of the class-scope explicit specialization eagerly. // We don't have support for lazy instantiation of an explicit specialization // yet, and MSVC eagerly instantiates in this case. if (D->isThisDeclarationADefinition() && SemaRef.InstantiateClass(D->getLocation(), InstD, D, TemplateArgs, TSK_ImplicitInstantiation, /*Complain=*/true)) return nullptr; return InstD; } Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *D) { TemplateArgumentListInfo VarTemplateArgsInfo; VarTemplateDecl *VarTemplate = D->getSpecializedTemplate(); assert(VarTemplate && "A template specialization without specialized template?"); // Substitute the current template arguments. const TemplateArgumentListInfo &TemplateArgsInfo = D->getTemplateArgsInfo(); VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo.getLAngleLoc()); VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo.getRAngleLoc()); if (SemaRef.Subst(TemplateArgsInfo.getArgumentArray(), TemplateArgsInfo.size(), VarTemplateArgsInfo, TemplateArgs)) return nullptr; // Check that the template argument list is well-formed for this template. SmallVector Converted; if (SemaRef.CheckTemplateArgumentList( VarTemplate, VarTemplate->getLocStart(), const_cast(VarTemplateArgsInfo), false, Converted)) return nullptr; // Find the variable template specialization declaration that // corresponds to these arguments. void *InsertPos = nullptr; if (VarTemplateSpecializationDecl *VarSpec = VarTemplate->findSpecialization( Converted, InsertPos)) // If we already have a variable template specialization, return it. return VarSpec; return VisitVarTemplateSpecializationDecl(VarTemplate, D, InsertPos, VarTemplateArgsInfo, Converted); } Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( VarTemplateDecl *VarTemplate, VarDecl *D, void *InsertPos, const TemplateArgumentListInfo &TemplateArgsInfo, ArrayRef Converted) { // Do substitution on the type of the declaration TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs, D->getTypeSpecStartLoc(), D->getDeclName()); if (!DI) return nullptr; if (DI->getType()->isFunctionType()) { SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function) << D->isStaticDataMember() << DI->getType(); return nullptr; } // Build the instantiated declaration VarTemplateSpecializationDecl *Var = VarTemplateSpecializationDecl::Create( SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), VarTemplate, DI->getType(), DI, D->getStorageClass(), Converted); Var->setTemplateArgsInfo(TemplateArgsInfo); if (InsertPos) VarTemplate->AddSpecialization(Var, InsertPos); // Substitute the nested name specifier, if any. if (SubstQualifier(D, Var)) return nullptr; SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner, StartingScope); return Var; } Decl *TemplateDeclInstantiator::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) { llvm_unreachable("@defs is not supported in Objective-C++"); } Decl *TemplateDeclInstantiator::VisitFriendTemplateDecl(FriendTemplateDecl *D) { // FIXME: We need to be able to instantiate FriendTemplateDecls. unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID( DiagnosticsEngine::Error, "cannot instantiate %0 yet"); SemaRef.Diag(D->getLocation(), DiagID) << D->getDeclKindName(); return nullptr; } Decl *TemplateDeclInstantiator::VisitDecl(Decl *D) { llvm_unreachable("Unexpected decl"); } Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner, const MultiLevelTemplateArgumentList &TemplateArgs) { TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs); if (D->isInvalidDecl()) return nullptr; return Instantiator.Visit(D); } /// \brief Instantiates a nested template parameter list in the current /// instantiation context. /// /// \param L The parameter list to instantiate /// /// \returns NULL if there was an error TemplateParameterList * TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) { // Get errors for all the parameters before bailing out. bool Invalid = false; unsigned N = L->size(); typedef SmallVector ParamVector; ParamVector Params; Params.reserve(N); for (auto &P : *L) { NamedDecl *D = cast_or_null(Visit(P)); Params.push_back(D); Invalid = Invalid || !D || D->isInvalidDecl(); } // Clean up if we had an error. if (Invalid) return nullptr; // Note: we substitute into associated constraints later Expr *const UninstantiatedRequiresClause = L->getRequiresClause(); TemplateParameterList *InstL = TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(), L->getLAngleLoc(), Params, L->getRAngleLoc(), UninstantiatedRequiresClause); return InstL; } /// \brief Instantiate the declaration of a class template partial /// specialization. /// /// \param ClassTemplate the (instantiated) class template that is partially // specialized by the instantiation of \p PartialSpec. /// /// \param PartialSpec the (uninstantiated) class template partial /// specialization that we are instantiating. /// /// \returns The instantiated partial specialization, if successful; otherwise, /// NULL to indicate an error. ClassTemplatePartialSpecializationDecl * TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( ClassTemplateDecl *ClassTemplate, ClassTemplatePartialSpecializationDecl *PartialSpec) { // Create a local instantiation scope for this class template partial // specialization, which will contain the instantiations of the template // parameters. LocalInstantiationScope Scope(SemaRef); // Substitute into the template parameters of the class template partial // specialization. TemplateParameterList *TempParams = PartialSpec->getTemplateParameters(); TemplateParameterList *InstParams = SubstTemplateParams(TempParams); if (!InstParams) return nullptr; // Substitute into the template arguments of the class template partial // specialization. const ASTTemplateArgumentListInfo *TemplArgInfo = PartialSpec->getTemplateArgsAsWritten(); TemplateArgumentListInfo InstTemplateArgs(TemplArgInfo->LAngleLoc, TemplArgInfo->RAngleLoc); if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(), TemplArgInfo->NumTemplateArgs, InstTemplateArgs, TemplateArgs)) return nullptr; // Check that the template argument list is well-formed for this // class template. SmallVector Converted; if (SemaRef.CheckTemplateArgumentList(ClassTemplate, PartialSpec->getLocation(), InstTemplateArgs, false, Converted)) return nullptr; // Check these arguments are valid for a template partial specialization. if (SemaRef.CheckTemplatePartialSpecializationArgs( PartialSpec->getLocation(), ClassTemplate, InstTemplateArgs.size(), Converted)) return nullptr; // Figure out where to insert this class template partial specialization // in the member template's set of class template partial specializations. void *InsertPos = nullptr; ClassTemplateSpecializationDecl *PrevDecl = ClassTemplate->findPartialSpecialization(Converted, InsertPos); // Build the canonical type that describes the converted template // arguments of the class template partial specialization. QualType CanonType = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate), Converted); // Build the fully-sugared type for this class template // specialization as the user wrote in the specialization // itself. This means that we'll pretty-print the type retrieved // from the specialization's declaration the way that the user // actually wrote the specialization, rather than formatting the // name based on the "canonical" representation used to store the // template arguments in the specialization. TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo( TemplateName(ClassTemplate), PartialSpec->getLocation(), InstTemplateArgs, CanonType); if (PrevDecl) { // We've already seen a partial specialization with the same template // parameters and template arguments. This can happen, for example, when // substituting the outer template arguments ends up causing two // class template partial specializations of a member class template // to have identical forms, e.g., // // template // struct Outer { // template struct Inner; // template struct Inner; // template struct Inner; // }; // // Outer outer; // error: the partial specializations of Inner // // have the same signature. SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared) << WrittenTy->getType(); SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here) << SemaRef.Context.getTypeDeclType(PrevDecl); return nullptr; } // Create the class template partial specialization declaration. ClassTemplatePartialSpecializationDecl *InstPartialSpec = ClassTemplatePartialSpecializationDecl::Create(SemaRef.Context, PartialSpec->getTagKind(), Owner, PartialSpec->getLocStart(), PartialSpec->getLocation(), InstParams, ClassTemplate, Converted, InstTemplateArgs, CanonType, nullptr); // Substitute the nested name specifier, if any. if (SubstQualifier(PartialSpec, InstPartialSpec)) return nullptr; InstPartialSpec->setInstantiatedFromMember(PartialSpec); InstPartialSpec->setTypeAsWritten(WrittenTy); // Check the completed partial specialization. SemaRef.CheckTemplatePartialSpecialization(InstPartialSpec); // Add this partial specialization to the set of class template partial // specializations. ClassTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/nullptr); return InstPartialSpec; } /// \brief Instantiate the declaration of a variable template partial /// specialization. /// /// \param VarTemplate the (instantiated) variable template that is partially /// specialized by the instantiation of \p PartialSpec. /// /// \param PartialSpec the (uninstantiated) variable template partial /// specialization that we are instantiating. /// /// \returns The instantiated partial specialization, if successful; otherwise, /// NULL to indicate an error. VarTemplatePartialSpecializationDecl * TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization( VarTemplateDecl *VarTemplate, VarTemplatePartialSpecializationDecl *PartialSpec) { // Create a local instantiation scope for this variable template partial // specialization, which will contain the instantiations of the template // parameters. LocalInstantiationScope Scope(SemaRef); // Substitute into the template parameters of the variable template partial // specialization. TemplateParameterList *TempParams = PartialSpec->getTemplateParameters(); TemplateParameterList *InstParams = SubstTemplateParams(TempParams); if (!InstParams) return nullptr; // Substitute into the template arguments of the variable template partial // specialization. const ASTTemplateArgumentListInfo *TemplArgInfo = PartialSpec->getTemplateArgsAsWritten(); TemplateArgumentListInfo InstTemplateArgs(TemplArgInfo->LAngleLoc, TemplArgInfo->RAngleLoc); if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(), TemplArgInfo->NumTemplateArgs, InstTemplateArgs, TemplateArgs)) return nullptr; // Check that the template argument list is well-formed for this // class template. SmallVector Converted; if (SemaRef.CheckTemplateArgumentList(VarTemplate, PartialSpec->getLocation(), InstTemplateArgs, false, Converted)) return nullptr; // Check these arguments are valid for a template partial specialization. if (SemaRef.CheckTemplatePartialSpecializationArgs( PartialSpec->getLocation(), VarTemplate, InstTemplateArgs.size(), Converted)) return nullptr; // Figure out where to insert this variable template partial specialization // in the member template's set of variable template partial specializations. void *InsertPos = nullptr; VarTemplateSpecializationDecl *PrevDecl = VarTemplate->findPartialSpecialization(Converted, InsertPos); // Build the canonical type that describes the converted template // arguments of the variable template partial specialization. QualType CanonType = SemaRef.Context.getTemplateSpecializationType( TemplateName(VarTemplate), Converted); // Build the fully-sugared type for this variable template // specialization as the user wrote in the specialization // itself. This means that we'll pretty-print the type retrieved // from the specialization's declaration the way that the user // actually wrote the specialization, rather than formatting the // name based on the "canonical" representation used to store the // template arguments in the specialization. TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo( TemplateName(VarTemplate), PartialSpec->getLocation(), InstTemplateArgs, CanonType); if (PrevDecl) { // We've already seen a partial specialization with the same template // parameters and template arguments. This can happen, for example, when // substituting the outer template arguments ends up causing two // variable template partial specializations of a member variable template // to have identical forms, e.g., // // template // struct Outer { // template pair p; // template pair p; // template pair p; // }; // // Outer outer; // error: the partial specializations of Inner // // have the same signature. SemaRef.Diag(PartialSpec->getLocation(), diag::err_var_partial_spec_redeclared) << WrittenTy->getType(); SemaRef.Diag(PrevDecl->getLocation(), diag::note_var_prev_partial_spec_here); return nullptr; } // Do substitution on the type of the declaration TypeSourceInfo *DI = SemaRef.SubstType( PartialSpec->getTypeSourceInfo(), TemplateArgs, PartialSpec->getTypeSpecStartLoc(), PartialSpec->getDeclName()); if (!DI) return nullptr; if (DI->getType()->isFunctionType()) { SemaRef.Diag(PartialSpec->getLocation(), diag::err_variable_instantiates_to_function) << PartialSpec->isStaticDataMember() << DI->getType(); return nullptr; } // Create the variable template partial specialization declaration. VarTemplatePartialSpecializationDecl *InstPartialSpec = VarTemplatePartialSpecializationDecl::Create( SemaRef.Context, Owner, PartialSpec->getInnerLocStart(), PartialSpec->getLocation(), InstParams, VarTemplate, DI->getType(), DI, PartialSpec->getStorageClass(), Converted, InstTemplateArgs); // Substitute the nested name specifier, if any. if (SubstQualifier(PartialSpec, InstPartialSpec)) return nullptr; InstPartialSpec->setInstantiatedFromMember(PartialSpec); InstPartialSpec->setTypeAsWritten(WrittenTy); // Check the completed partial specialization. SemaRef.CheckTemplatePartialSpecialization(InstPartialSpec); // Add this partial specialization to the set of variable template partial // specializations. The instantiation of the initializer is not necessary. VarTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/nullptr); SemaRef.BuildVariableInstantiation(InstPartialSpec, PartialSpec, TemplateArgs, LateAttrs, Owner, StartingScope); return InstPartialSpec; } TypeSourceInfo* TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, SmallVectorImpl &Params) { TypeSourceInfo *OldTInfo = D->getTypeSourceInfo(); assert(OldTInfo && "substituting function without type source info"); assert(Params.empty() && "parameter vector is non-empty at start"); CXXRecordDecl *ThisContext = nullptr; unsigned ThisTypeQuals = 0; if (CXXMethodDecl *Method = dyn_cast(D)) { ThisContext = cast(Owner); ThisTypeQuals = Method->getTypeQualifiers(); } TypeSourceInfo *NewTInfo = SemaRef.SubstFunctionDeclType(OldTInfo, TemplateArgs, D->getTypeSpecStartLoc(), D->getDeclName(), ThisContext, ThisTypeQuals); if (!NewTInfo) return nullptr; TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens(); if (FunctionProtoTypeLoc OldProtoLoc = OldTL.getAs()) { if (NewTInfo != OldTInfo) { // Get parameters from the new type info. TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens(); FunctionProtoTypeLoc NewProtoLoc = NewTL.castAs(); unsigned NewIdx = 0; for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc.getNumParams(); OldIdx != NumOldParams; ++OldIdx) { ParmVarDecl *OldParam = OldProtoLoc.getParam(OldIdx); LocalInstantiationScope *Scope = SemaRef.CurrentInstantiationScope; Optional NumArgumentsInExpansion; if (OldParam->isParameterPack()) NumArgumentsInExpansion = SemaRef.getNumArgumentsInExpansion(OldParam->getType(), TemplateArgs); if (!NumArgumentsInExpansion) { // Simple case: normal parameter, or a parameter pack that's // instantiated to a (still-dependent) parameter pack. ParmVarDecl *NewParam = NewProtoLoc.getParam(NewIdx++); Params.push_back(NewParam); Scope->InstantiatedLocal(OldParam, NewParam); } else { // Parameter pack expansion: make the instantiation an argument pack. Scope->MakeInstantiatedLocalArgPack(OldParam); for (unsigned I = 0; I != *NumArgumentsInExpansion; ++I) { ParmVarDecl *NewParam = NewProtoLoc.getParam(NewIdx++); Params.push_back(NewParam); Scope->InstantiatedLocalPackArg(OldParam, NewParam); } } } } else { // The function type itself was not dependent and therefore no // substitution occurred. However, we still need to instantiate // the function parameters themselves. const FunctionProtoType *OldProto = cast(OldProtoLoc.getType()); for (unsigned i = 0, i_end = OldProtoLoc.getNumParams(); i != i_end; ++i) { ParmVarDecl *OldParam = OldProtoLoc.getParam(i); if (!OldParam) { Params.push_back(SemaRef.BuildParmVarDeclForTypedef( D, D->getLocation(), OldProto->getParamType(i))); continue; } ParmVarDecl *Parm = cast_or_null(VisitParmVarDecl(OldParam)); if (!Parm) return nullptr; Params.push_back(Parm); } } } else { // If the type of this function, after ignoring parentheses, is not // *directly* a function type, then we're instantiating a function that // was declared via a typedef or with attributes, e.g., // // typedef int functype(int, int); // functype func; // int __cdecl meth(int, int); // // In this case, we'll just go instantiate the ParmVarDecls that we // synthesized in the method declaration. SmallVector ParamTypes; Sema::ExtParameterInfoBuilder ExtParamInfos; if (SemaRef.SubstParmTypes(D->getLocation(), D->parameters(), nullptr, TemplateArgs, ParamTypes, &Params, ExtParamInfos)) return nullptr; } return NewTInfo; } /// Introduce the instantiated function parameters into the local /// instantiation scope, and set the parameter names to those used /// in the template. static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, const FunctionDecl *PatternDecl, LocalInstantiationScope &Scope, const MultiLevelTemplateArgumentList &TemplateArgs) { unsigned FParamIdx = 0; for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) { const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I); if (!PatternParam->isParameterPack()) { // Simple case: not a parameter pack. assert(FParamIdx < Function->getNumParams()); ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); FunctionParam->setDeclName(PatternParam->getDeclName()); // If the parameter's type is not dependent, update it to match the type // in the pattern. They can differ in top-level cv-qualifiers, and we want // the pattern's type here. If the type is dependent, they can't differ, // per core issue 1668. Substitute into the type from the pattern, in case // it's instantiation-dependent. // FIXME: Updating the type to work around this is at best fragile. if (!PatternDecl->getType()->isDependentType()) { QualType T = S.SubstType(PatternParam->getType(), TemplateArgs, FunctionParam->getLocation(), FunctionParam->getDeclName()); if (T.isNull()) return true; FunctionParam->setType(T); } Scope.InstantiatedLocal(PatternParam, FunctionParam); ++FParamIdx; continue; } // Expand the parameter pack. Scope.MakeInstantiatedLocalArgPack(PatternParam); Optional NumArgumentsInExpansion = S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs); assert(NumArgumentsInExpansion && "should only be called when all template arguments are known"); QualType PatternType = PatternParam->getType()->castAs()->getPattern(); for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) { ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); FunctionParam->setDeclName(PatternParam->getDeclName()); if (!PatternDecl->getType()->isDependentType()) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, Arg); QualType T = S.SubstType(PatternType, TemplateArgs, FunctionParam->getLocation(), FunctionParam->getDeclName()); if (T.isNull()) return true; FunctionParam->setType(T); } Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam); ++FParamIdx; } } return false; } void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, FunctionDecl *Decl) { const FunctionProtoType *Proto = Decl->getType()->castAs(); if (Proto->getExceptionSpecType() != EST_Uninstantiated) return; InstantiatingTemplate Inst(*this, PointOfInstantiation, Decl, InstantiatingTemplate::ExceptionSpecification()); if (Inst.isInvalid()) { // We hit the instantiation depth limit. Clear the exception specification // so that our callers don't have to cope with EST_Uninstantiated. UpdateExceptionSpec(Decl, EST_None); return; } if (Inst.isAlreadyInstantiating()) { // This exception specification indirectly depends on itself. Reject. // FIXME: Corresponding rule in the standard? Diag(PointOfInstantiation, diag::err_exception_spec_cycle) << Decl; UpdateExceptionSpec(Decl, EST_None); return; } // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. Sema::ContextRAII savedContext(*this, Decl); LocalInstantiationScope Scope(*this); MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true); FunctionDecl *Template = Proto->getExceptionSpecTemplate(); if (addInstantiatedParametersToScope(*this, Decl, Template, Scope, TemplateArgs)) { UpdateExceptionSpec(Decl, EST_None); return; } SubstExceptionSpec(Decl, Template->getType()->castAs(), TemplateArgs); } /// \brief Initializes the common fields of an instantiation function /// declaration (New) from the corresponding fields of its template (Tmpl). /// /// \returns true if there was an error bool TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl) { if (Tmpl->isDeleted()) New->setDeletedAsWritten(); New->setImplicit(Tmpl->isImplicit()); // Forward the mangling number from the template to the instantiated decl. SemaRef.Context.setManglingNumber(New, SemaRef.Context.getManglingNumber(Tmpl)); // If we are performing substituting explicitly-specified template arguments // or deduced template arguments into a function template and we reach this // point, we are now past the point where SFINAE applies and have committed // to keeping the new function template specialization. We therefore // convert the active template instantiation for the function template // into a template instantiation for this specific function template // specialization, which is not a SFINAE context, so that we diagnose any // further errors in the declaration itself. typedef Sema::CodeSynthesisContext ActiveInstType; ActiveInstType &ActiveInst = SemaRef.CodeSynthesisContexts.back(); if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution || ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) { if (FunctionTemplateDecl *FunTmpl = dyn_cast(ActiveInst.Entity)) { assert(FunTmpl->getTemplatedDecl() == Tmpl && "Deduction from the wrong function template?"); (void) FunTmpl; ActiveInst.Kind = ActiveInstType::TemplateInstantiation; ActiveInst.Entity = New; } } const FunctionProtoType *Proto = Tmpl->getType()->getAs(); assert(Proto && "Function template without prototype?"); if (Proto->hasExceptionSpec() || Proto->getNoReturnAttr()) { FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); // DR1330: In C++11, defer instantiation of a non-trivial // exception specification. // DR1484: Local classes and their members are instantiated along with the // containing function. if (SemaRef.getLangOpts().CPlusPlus11 && EPI.ExceptionSpec.Type != EST_None && EPI.ExceptionSpec.Type != EST_DynamicNone && EPI.ExceptionSpec.Type != EST_BasicNoexcept && !Tmpl->isLexicallyWithinFunctionOrMethod()) { FunctionDecl *ExceptionSpecTemplate = Tmpl; if (EPI.ExceptionSpec.Type == EST_Uninstantiated) ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate; ExceptionSpecificationType NewEST = EST_Uninstantiated; if (EPI.ExceptionSpec.Type == EST_Unevaluated) NewEST = EST_Unevaluated; // Mark the function has having an uninstantiated exception specification. const FunctionProtoType *NewProto = New->getType()->getAs(); assert(NewProto && "Template instantiation without function prototype?"); EPI = NewProto->getExtProtoInfo(); EPI.ExceptionSpec.Type = NewEST; EPI.ExceptionSpec.SourceDecl = New; EPI.ExceptionSpec.SourceTemplate = ExceptionSpecTemplate; New->setType(SemaRef.Context.getFunctionType( NewProto->getReturnType(), NewProto->getParamTypes(), EPI)); } else { Sema::ContextRAII SwitchContext(SemaRef, New); SemaRef.SubstExceptionSpec(New, Proto, TemplateArgs); } } // Get the definition. Leaves the variable unchanged if undefined. const FunctionDecl *Definition = Tmpl; Tmpl->isDefined(Definition); SemaRef.InstantiateAttrs(TemplateArgs, Definition, New, LateAttrs, StartingScope); return false; } /// \brief Initializes common fields of an instantiated method /// declaration (New) from the corresponding fields of its template /// (Tmpl). /// /// \returns true if there was an error bool TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl) { if (InitFunctionInstantiation(New, Tmpl)) return true; New->setAccess(Tmpl->getAccess()); if (Tmpl->isVirtualAsWritten()) New->setVirtualAsWritten(true); // FIXME: New needs a pointer to Tmpl return false; } /// In the MS ABI, we need to instantiate default arguments of dllexported /// default constructors along with the constructor definition. This allows IR /// gen to emit a constructor closure which calls the default constructor with /// its default arguments. static void InstantiateDefaultCtorDefaultArgs(Sema &S, CXXConstructorDecl *Ctor) { assert(S.Context.getTargetInfo().getCXXABI().isMicrosoft() && Ctor->isDefaultConstructor()); unsigned NumParams = Ctor->getNumParams(); if (NumParams == 0) return; DLLExportAttr *Attr = Ctor->getAttr(); if (!Attr) return; for (unsigned I = 0; I != NumParams; ++I) { (void)S.CheckCXXDefaultArgExpr(Attr->getLocation(), Ctor, Ctor->getParamDecl(I)); S.DiscardCleanupsInEvaluationContext(); } } /// \brief Instantiate the definition of the given function from its /// template. /// /// \param PointOfInstantiation the point at which the instantiation was /// required. Note that this is not precisely a "point of instantiation" /// for the function, but it's close. /// /// \param Function the already-instantiated declaration of a /// function template specialization or member function of a class template /// specialization. /// /// \param Recursive if true, recursively instantiates any functions that /// are required by this instantiation. /// /// \param DefinitionRequired if true, then we are performing an explicit /// instantiation where the body of the function is required. Complain if /// there is no such body. void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, FunctionDecl *Function, bool Recursive, bool DefinitionRequired, bool AtEndOfTU) { if (Function->isInvalidDecl() || Function->isDefined()) return; // Never instantiate an explicit specialization except if it is a class scope // explicit specialization. TemplateSpecializationKind TSK = Function->getTemplateSpecializationKind(); if (TSK == TSK_ExplicitSpecialization && !Function->getClassScopeSpecializationPattern()) return; // Find the function body that we'll be substituting. const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern(); assert(PatternDecl && "instantiating a non-template"); const FunctionDecl *PatternDef = PatternDecl->getDefinition(); Stmt *Pattern = nullptr; if (PatternDef) { Pattern = PatternDef->getBody(PatternDef); PatternDecl = PatternDef; if (PatternDef->willHaveBody()) PatternDef = nullptr; } // FIXME: We need to track the instantiation stack in order to know which // definitions should be visible within this instantiation. if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Function, Function->getInstantiatedFromMemberFunction(), PatternDecl, PatternDef, TSK, /*Complain*/DefinitionRequired)) { if (DefinitionRequired) Function->setInvalidDecl(); else if (TSK == TSK_ExplicitInstantiationDefinition) { // Try again at the end of the translation unit (at which point a // definition will be required). assert(!Recursive); Function->setInstantiationIsPending(true); PendingInstantiations.push_back( std::make_pair(Function, PointOfInstantiation)); } else if (TSK == TSK_ImplicitInstantiation) { if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) { Diag(PointOfInstantiation, diag::warn_func_template_missing) << Function; Diag(PatternDecl->getLocation(), diag::note_forward_template_decl); if (getLangOpts().CPlusPlus11) Diag(PointOfInstantiation, diag::note_inst_declaration_hint) << Function; } } return; } // Postpone late parsed template instantiations. if (PatternDecl->isLateTemplateParsed() && !LateTemplateParser) { Function->setInstantiationIsPending(true); PendingInstantiations.push_back( std::make_pair(Function, PointOfInstantiation)); return; } // If we're performing recursive template instantiation, create our own // queue of pending implicit instantiations that we will instantiate later, // while we're still within our own instantiation context. // This has to happen before LateTemplateParser below is called, so that // it marks vtables used in late parsed templates as used. GlobalEagerInstantiationScope GlobalInstantiations(*this, /*Enabled=*/Recursive); LocalEagerInstantiationScope LocalInstantiations(*this); // Call the LateTemplateParser callback if there is a need to late parse // a templated function definition. if (!Pattern && PatternDecl->isLateTemplateParsed() && LateTemplateParser) { // FIXME: Optimize to allow individual templates to be deserialized. if (PatternDecl->isFromASTFile()) ExternalSource->ReadLateParsedTemplates(LateParsedTemplateMap); auto LPTIter = LateParsedTemplateMap.find(PatternDecl); assert(LPTIter != LateParsedTemplateMap.end() && "missing LateParsedTemplate"); LateTemplateParser(OpaqueParser, *LPTIter->second); Pattern = PatternDecl->getBody(PatternDecl); } // Note, we should never try to instantiate a deleted function template. assert((Pattern || PatternDecl->isDefaulted()) && "unexpected kind of function template definition"); // C++1y [temp.explicit]p10: // Except for inline functions, declarations with types deduced from their // initializer or return value, and class template specializations, other // explicit instantiation declarations have the effect of suppressing the // implicit instantiation of the entity to which they refer. if (TSK == TSK_ExplicitInstantiationDeclaration && !PatternDecl->isInlined() && !PatternDecl->getReturnType()->getContainedAutoType()) return; if (PatternDecl->isInlined()) { // Function, and all later redeclarations of it (from imported modules, // for instance), are now implicitly inline. for (auto *D = Function->getMostRecentDecl(); /**/; D = D->getPreviousDecl()) { D->setImplicitlyInline(); if (D == Function) break; } } InstantiatingTemplate Inst(*this, PointOfInstantiation, Function); if (Inst.isInvalid() || Inst.isAlreadyInstantiating()) return; PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(), "instantiating function definition"); // The instantiation is visible here, even if it was first declared in an // unimported module. Function->setVisibleDespiteOwningModule(); // Copy the inner loc start from the pattern. Function->setInnerLocStart(PatternDecl->getInnerLocStart()); EnterExpressionEvaluationContext EvalContext( *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); // Introduce a new scope where local variable instantiations will be // recorded, unless we're actually a member function within a local // class, in which case we need to merge our results with the parent // scope (of the enclosing function). bool MergeWithParentScope = false; if (CXXRecordDecl *Rec = dyn_cast(Function->getDeclContext())) MergeWithParentScope = Rec->isLocalClass(); LocalInstantiationScope Scope(*this, MergeWithParentScope); if (PatternDecl->isDefaulted()) SetDeclDefaulted(Function, PatternDecl->getLocation()); else { MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl); // Substitute into the qualifier; we can get a substitution failure here // through evil use of alias templates. // FIXME: Is CurContext correct for this? Should we go to the (instantiation // of the) lexical context of the pattern? SubstQualifier(*this, PatternDecl, Function, TemplateArgs); ActOnStartOfFunctionDef(nullptr, Function); // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. Sema::ContextRAII savedContext(*this, Function); if (addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope, TemplateArgs)) return; if (CXXConstructorDecl *Ctor = dyn_cast(Function)) { // If this is a constructor, instantiate the member initializers. InstantiateMemInitializers(Ctor, cast(PatternDecl), TemplateArgs); // If this is an MS ABI dllexport default constructor, instantiate any // default arguments. if (Context.getTargetInfo().getCXXABI().isMicrosoft() && Ctor->isDefaultConstructor()) { InstantiateDefaultCtorDefaultArgs(*this, Ctor); } } // Instantiate the function body. StmtResult Body = SubstStmt(Pattern, TemplateArgs); if (Body.isInvalid()) Function->setInvalidDecl(); // FIXME: finishing the function body while in an expression evaluation // context seems wrong. Investigate more. ActOnFinishFunctionBody(Function, Body.get(), /*IsInstantiation=*/true); PerformDependentDiagnostics(PatternDecl, TemplateArgs); if (auto *Listener = getASTMutationListener()) Listener->FunctionDefinitionInstantiated(Function); savedContext.pop(); } DeclGroupRef DG(Function); Consumer.HandleTopLevelDecl(DG); // This class may have local implicit instantiations that need to be // instantiation within this scope. LocalInstantiations.perform(); Scope.Exit(); GlobalInstantiations.perform(); } VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( VarTemplateDecl *VarTemplate, VarDecl *FromVar, const TemplateArgumentList &TemplateArgList, const TemplateArgumentListInfo &TemplateArgsInfo, SmallVectorImpl &Converted, SourceLocation PointOfInstantiation, void *InsertPos, LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *StartingScope) { if (FromVar->isInvalidDecl()) return nullptr; InstantiatingTemplate Inst(*this, PointOfInstantiation, FromVar); if (Inst.isInvalid()) return nullptr; MultiLevelTemplateArgumentList TemplateArgLists; TemplateArgLists.addOuterTemplateArguments(&TemplateArgList); // Instantiate the first declaration of the variable template: for a partial // specialization of a static data member template, the first declaration may // or may not be the declaration in the class; if it's in the class, we want // to instantiate a member in the class (a declaration), and if it's outside, // we want to instantiate a definition. // // If we're instantiating an explicitly-specialized member template or member // partial specialization, don't do this. The member specialization completely // replaces the original declaration in this case. bool IsMemberSpec = false; if (VarTemplatePartialSpecializationDecl *PartialSpec = dyn_cast(FromVar)) IsMemberSpec = PartialSpec->isMemberSpecialization(); else if (VarTemplateDecl *FromTemplate = FromVar->getDescribedVarTemplate()) IsMemberSpec = FromTemplate->isMemberSpecialization(); if (!IsMemberSpec) FromVar = FromVar->getFirstDecl(); MultiLevelTemplateArgumentList MultiLevelList(TemplateArgList); TemplateDeclInstantiator Instantiator(*this, FromVar->getDeclContext(), MultiLevelList); // TODO: Set LateAttrs and StartingScope ... return cast_or_null( Instantiator.VisitVarTemplateSpecializationDecl( VarTemplate, FromVar, InsertPos, TemplateArgsInfo, Converted)); } /// \brief Instantiates a variable template specialization by completing it /// with appropriate type information and initializer. VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl, const MultiLevelTemplateArgumentList &TemplateArgs) { // Do substitution on the type of the declaration TypeSourceInfo *DI = SubstType(PatternDecl->getTypeSourceInfo(), TemplateArgs, PatternDecl->getTypeSpecStartLoc(), PatternDecl->getDeclName()); if (!DI) return nullptr; // Update the type of this variable template specialization. VarSpec->setType(DI->getType()); // Instantiate the initializer. InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs); return VarSpec; } /// BuildVariableInstantiation - Used after a new variable has been created. /// Sets basic variable data and decides whether to postpone the /// variable instantiation. void Sema::BuildVariableInstantiation( VarDecl *NewVar, VarDecl *OldVar, const MultiLevelTemplateArgumentList &TemplateArgs, LateInstantiatedAttrVec *LateAttrs, DeclContext *Owner, LocalInstantiationScope *StartingScope, bool InstantiatingVarTemplate) { // If we are instantiating a local extern declaration, the // instantiation belongs lexically to the containing function. // If we are instantiating a static data member defined // out-of-line, the instantiation will have the same lexical // context (which will be a namespace scope) as the template. if (OldVar->isLocalExternDecl()) { NewVar->setLocalExternDecl(); NewVar->setLexicalDeclContext(Owner); } else if (OldVar->isOutOfLine()) NewVar->setLexicalDeclContext(OldVar->getLexicalDeclContext()); NewVar->setTSCSpec(OldVar->getTSCSpec()); NewVar->setInitStyle(OldVar->getInitStyle()); NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl()); NewVar->setConstexpr(OldVar->isConstexpr()); NewVar->setInitCapture(OldVar->isInitCapture()); NewVar->setPreviousDeclInSameBlockScope( OldVar->isPreviousDeclInSameBlockScope()); NewVar->setAccess(OldVar->getAccess()); if (!OldVar->isStaticDataMember()) { if (OldVar->isUsed(false)) NewVar->setIsUsed(); NewVar->setReferenced(OldVar->isReferenced()); } InstantiateAttrs(TemplateArgs, OldVar, NewVar, LateAttrs, StartingScope); LookupResult Previous( *this, NewVar->getDeclName(), NewVar->getLocation(), NewVar->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage : Sema::LookupOrdinaryName, Sema::ForRedeclaration); if (NewVar->isLocalExternDecl() && OldVar->getPreviousDecl() && (!OldVar->getPreviousDecl()->getDeclContext()->isDependentContext() || OldVar->getPreviousDecl()->getDeclContext()==OldVar->getDeclContext())) { // We have a previous declaration. Use that one, so we merge with the // right type. if (NamedDecl *NewPrev = FindInstantiatedDecl( NewVar->getLocation(), OldVar->getPreviousDecl(), TemplateArgs)) Previous.addDecl(NewPrev); } else if (!isa(NewVar) && OldVar->hasLinkage()) LookupQualifiedName(Previous, NewVar->getDeclContext(), false); CheckVariableDeclaration(NewVar, Previous); if (!InstantiatingVarTemplate) { NewVar->getLexicalDeclContext()->addHiddenDecl(NewVar); if (!NewVar->isLocalExternDecl() || !NewVar->getPreviousDecl()) NewVar->getDeclContext()->makeDeclVisibleInContext(NewVar); } if (!OldVar->isOutOfLine()) { if (NewVar->getDeclContext()->isFunctionOrMethod()) CurrentInstantiationScope->InstantiatedLocal(OldVar, NewVar); } // Link instantiations of static data members back to the template from // which they were instantiated. if (NewVar->isStaticDataMember() && !InstantiatingVarTemplate) NewVar->setInstantiationOfStaticDataMember(OldVar, TSK_ImplicitInstantiation); // Forward the mangling number from the template to the instantiated decl. Context.setManglingNumber(NewVar, Context.getManglingNumber(OldVar)); Context.setStaticLocalNumber(NewVar, Context.getStaticLocalNumber(OldVar)); // Delay instantiation of the initializer for variable templates or inline // static data members until a definition of the variable is needed. We need // it right away if the type contains 'auto'. if ((!isa(NewVar) && !InstantiatingVarTemplate && !(OldVar->isInline() && OldVar->isThisDeclarationADefinition())) || NewVar->getType()->isUndeducedType()) InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs); // Diagnose unused local variables with dependent types, where the diagnostic // will have been deferred. if (!NewVar->isInvalidDecl() && NewVar->getDeclContext()->isFunctionOrMethod() && OldVar->getType()->isDependentType()) DiagnoseUnusedDecl(NewVar); } /// \brief Instantiate the initializer of a variable. void Sema::InstantiateVariableInitializer( VarDecl *Var, VarDecl *OldVar, const MultiLevelTemplateArgumentList &TemplateArgs) { // We propagate the 'inline' flag with the initializer, because it // would otherwise imply that the variable is a definition for a // non-static data member. if (OldVar->isInlineSpecified()) Var->setInlineSpecified(); else if (OldVar->isInline()) Var->setImplicitlyInline(); if (OldVar->getInit()) { if (Var->isStaticDataMember() && !OldVar->isOutOfLine()) PushExpressionEvaluationContext( Sema::ExpressionEvaluationContext::ConstantEvaluated, OldVar); else PushExpressionEvaluationContext( Sema::ExpressionEvaluationContext::PotentiallyEvaluated, OldVar); // Instantiate the initializer. ExprResult Init; { ContextRAII SwitchContext(*this, Var->getDeclContext()); Init = SubstInitializer(OldVar->getInit(), TemplateArgs, OldVar->getInitStyle() == VarDecl::CallInit); } if (!Init.isInvalid()) { Expr *InitExpr = Init.get(); if (Var->hasAttr() && (!InitExpr || !InitExpr->isConstantInitializer(getASTContext(), false))) { // Do not dynamically initialize dllimport variables. } else if (InitExpr) { bool DirectInit = OldVar->isDirectInit(); AddInitializerToDecl(Var, InitExpr, DirectInit); } else ActOnUninitializedDecl(Var); } else { // FIXME: Not too happy about invalidating the declaration // because of a bogus initializer. Var->setInvalidDecl(); } PopExpressionEvaluationContext(); } else { if (Var->isStaticDataMember()) { if (!Var->isOutOfLine()) return; // If the declaration inside the class had an initializer, don't add // another one to the out-of-line definition. if (OldVar->getFirstDecl()->hasInit()) return; } // We'll add an initializer to a for-range declaration later. if (Var->isCXXForRangeDecl()) return; ActOnUninitializedDecl(Var); } } /// \brief Instantiate the definition of the given variable from its /// template. /// /// \param PointOfInstantiation the point at which the instantiation was /// required. Note that this is not precisely a "point of instantiation" /// for the function, but it's close. /// /// \param Var the already-instantiated declaration of a static member /// variable of a class template specialization. /// /// \param Recursive if true, recursively instantiates any functions that /// are required by this instantiation. /// /// \param DefinitionRequired if true, then we are performing an explicit /// instantiation where an out-of-line definition of the member variable /// is required. Complain if there is no such definition. void Sema::InstantiateStaticDataMemberDefinition( SourceLocation PointOfInstantiation, VarDecl *Var, bool Recursive, bool DefinitionRequired) { InstantiateVariableDefinition(PointOfInstantiation, Var, Recursive, DefinitionRequired); } void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, VarDecl *Var, bool Recursive, bool DefinitionRequired, bool AtEndOfTU) { if (Var->isInvalidDecl()) return; VarTemplateSpecializationDecl *VarSpec = dyn_cast(Var); VarDecl *PatternDecl = nullptr, *Def = nullptr; MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(Var); if (VarSpec) { // If this is a variable template specialization, make sure that it is // non-dependent, then find its instantiation pattern. bool InstantiationDependent = false; assert(!TemplateSpecializationType::anyDependentTemplateArguments( VarSpec->getTemplateArgsInfo(), InstantiationDependent) && "Only instantiate variable template specializations that are " "not type-dependent"); (void)InstantiationDependent; // Find the variable initialization that we'll be substituting. If the // pattern was instantiated from a member template, look back further to // find the real pattern. assert(VarSpec->getSpecializedTemplate() && "Specialization without specialized template?"); llvm::PointerUnion PatternPtr = VarSpec->getSpecializedTemplateOrPartial(); if (PatternPtr.is()) { VarTemplatePartialSpecializationDecl *Tmpl = PatternPtr.get(); while (VarTemplatePartialSpecializationDecl *From = Tmpl->getInstantiatedFromMember()) { if (Tmpl->isMemberSpecialization()) break; Tmpl = From; } PatternDecl = Tmpl; } else { VarTemplateDecl *Tmpl = PatternPtr.get(); while (VarTemplateDecl *From = Tmpl->getInstantiatedFromMemberTemplate()) { if (Tmpl->isMemberSpecialization()) break; Tmpl = From; } PatternDecl = Tmpl->getTemplatedDecl(); } // If this is a static data member template, there might be an // uninstantiated initializer on the declaration. If so, instantiate // it now. if (PatternDecl->isStaticDataMember() && (PatternDecl = PatternDecl->getFirstDecl())->hasInit() && !Var->hasInit()) { // FIXME: Factor out the duplicated instantiation context setup/tear down // code here. InstantiatingTemplate Inst(*this, PointOfInstantiation, Var); if (Inst.isInvalid() || Inst.isAlreadyInstantiating()) return; PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(), "instantiating variable initializer"); // The instantiation is visible here, even if it was first declared in an // unimported module. Var->setVisibleDespiteOwningModule(); // If we're performing recursive template instantiation, create our own // queue of pending implicit instantiations that we will instantiate // later, while we're still within our own instantiation context. GlobalEagerInstantiationScope GlobalInstantiations(*this, /*Enabled=*/Recursive); LocalInstantiationScope Local(*this); LocalEagerInstantiationScope LocalInstantiations(*this); // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. ContextRAII PreviousContext(*this, Var->getDeclContext()); InstantiateVariableInitializer(Var, PatternDecl, TemplateArgs); PreviousContext.pop(); // This variable may have local implicit instantiations that need to be // instantiated within this scope. LocalInstantiations.perform(); Local.Exit(); GlobalInstantiations.perform(); } // Find actual definition Def = PatternDecl->getDefinition(getASTContext()); } else { // If this is a static data member, find its out-of-line definition. assert(Var->isStaticDataMember() && "not a static data member?"); PatternDecl = Var->getInstantiatedFromStaticDataMember(); assert(PatternDecl && "data member was not instantiated from a template?"); assert(PatternDecl->isStaticDataMember() && "not a static data member?"); Def = PatternDecl->getDefinition(); } TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind(); // If we don't have a definition of the variable template, we won't perform // any instantiation. Rather, we rely on the user to instantiate this // definition (or provide a specialization for it) in another translation // unit. if (!Def && !DefinitionRequired) { if (TSK == TSK_ExplicitInstantiationDefinition) { PendingInstantiations.push_back( std::make_pair(Var, PointOfInstantiation)); } else if (TSK == TSK_ImplicitInstantiation) { // Warn about missing definition at the end of translation unit. if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) { Diag(PointOfInstantiation, diag::warn_var_template_missing) << Var; Diag(PatternDecl->getLocation(), diag::note_forward_template_decl); if (getLangOpts().CPlusPlus11) Diag(PointOfInstantiation, diag::note_inst_declaration_hint) << Var; } return; } } // FIXME: We need to track the instantiation stack in order to know which // definitions should be visible within this instantiation. // FIXME: Produce diagnostics when Var->getInstantiatedFromStaticDataMember(). if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Var, /*InstantiatedFromMember*/false, PatternDecl, Def, TSK, /*Complain*/DefinitionRequired)) return; // Never instantiate an explicit specialization. if (TSK == TSK_ExplicitSpecialization) return; // C++11 [temp.explicit]p10: // Except for inline functions, [...] explicit instantiation declarations // have the effect of suppressing the implicit instantiation of the entity // to which they refer. if (TSK == TSK_ExplicitInstantiationDeclaration) return; // Make sure to pass the instantiated variable to the consumer at the end. struct PassToConsumerRAII { ASTConsumer &Consumer; VarDecl *Var; PassToConsumerRAII(ASTConsumer &Consumer, VarDecl *Var) : Consumer(Consumer), Var(Var) { } ~PassToConsumerRAII() { Consumer.HandleCXXStaticMemberVarInstantiation(Var); } } PassToConsumerRAII(Consumer, Var); // If we already have a definition, we're done. if (VarDecl *Def = Var->getDefinition()) { // We may be explicitly instantiating something we've already implicitly // instantiated. Def->setTemplateSpecializationKind(Var->getTemplateSpecializationKind(), PointOfInstantiation); return; } InstantiatingTemplate Inst(*this, PointOfInstantiation, Var); if (Inst.isInvalid() || Inst.isAlreadyInstantiating()) return; PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(), "instantiating variable definition"); // If we're performing recursive template instantiation, create our own // queue of pending implicit instantiations that we will instantiate later, // while we're still within our own instantiation context. GlobalEagerInstantiationScope GlobalInstantiations(*this, /*Enabled=*/Recursive); // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. ContextRAII PreviousContext(*this, Var->getDeclContext()); LocalInstantiationScope Local(*this); LocalEagerInstantiationScope LocalInstantiations(*this); VarDecl *OldVar = Var; if (Def->isStaticDataMember() && !Def->isOutOfLine()) { // We're instantiating an inline static data member whose definition was // provided inside the class. InstantiateVariableInitializer(Var, Def, TemplateArgs); } else if (!VarSpec) { Var = cast_or_null(SubstDecl(Def, Var->getDeclContext(), TemplateArgs)); } else if (Var->isStaticDataMember() && Var->getLexicalDeclContext()->isRecord()) { // We need to instantiate the definition of a static data member template, // and all we have is the in-class declaration of it. Instantiate a separate // declaration of the definition. TemplateDeclInstantiator Instantiator(*this, Var->getDeclContext(), TemplateArgs); Var = cast_or_null(Instantiator.VisitVarTemplateSpecializationDecl( VarSpec->getSpecializedTemplate(), Def, nullptr, VarSpec->getTemplateArgsInfo(), VarSpec->getTemplateArgs().asArray())); if (Var) { llvm::PointerUnion PatternPtr = VarSpec->getSpecializedTemplateOrPartial(); if (VarTemplatePartialSpecializationDecl *Partial = PatternPtr.dyn_cast()) cast(Var)->setInstantiationOf( Partial, &VarSpec->getTemplateInstantiationArgs()); // Merge the definition with the declaration. LookupResult R(*this, Var->getDeclName(), Var->getLocation(), LookupOrdinaryName, ForRedeclaration); R.addDecl(OldVar); MergeVarDecl(Var, R); // Attach the initializer. InstantiateVariableInitializer(Var, Def, TemplateArgs); } } else // Complete the existing variable's definition with an appropriately // substituted type and initializer. Var = CompleteVarTemplateSpecializationDecl(VarSpec, Def, TemplateArgs); PreviousContext.pop(); if (Var) { PassToConsumerRAII.Var = Var; Var->setTemplateSpecializationKind(OldVar->getTemplateSpecializationKind(), OldVar->getPointOfInstantiation()); } // This variable may have local implicit instantiations that need to be // instantiated within this scope. LocalInstantiations.perform(); Local.Exit(); GlobalInstantiations.perform(); } void Sema::InstantiateMemInitializers(CXXConstructorDecl *New, const CXXConstructorDecl *Tmpl, const MultiLevelTemplateArgumentList &TemplateArgs) { SmallVector NewInits; bool AnyErrors = Tmpl->isInvalidDecl(); // Instantiate all the initializers. for (const auto *Init : Tmpl->inits()) { // Only instantiate written initializers, let Sema re-construct implicit // ones. if (!Init->isWritten()) continue; SourceLocation EllipsisLoc; if (Init->isPackExpansion()) { // This is a pack expansion. We should expand it now. TypeLoc BaseTL = Init->getTypeSourceInfo()->getTypeLoc(); SmallVector Unexpanded; collectUnexpandedParameterPacks(BaseTL, Unexpanded); collectUnexpandedParameterPacks(Init->getInit(), Unexpanded); bool ShouldExpand = false; bool RetainExpansion = false; Optional NumExpansions; if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(), BaseTL.getSourceRange(), Unexpanded, TemplateArgs, ShouldExpand, RetainExpansion, NumExpansions)) { AnyErrors = true; New->setInvalidDecl(); continue; } assert(ShouldExpand && "Partial instantiation of base initializer?"); // Loop over all of the arguments in the argument pack(s), for (unsigned I = 0; I != *NumExpansions; ++I) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I); // Instantiate the initializer. ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs, /*CXXDirectInit=*/true); if (TempInit.isInvalid()) { AnyErrors = true; break; } // Instantiate the base type. TypeSourceInfo *BaseTInfo = SubstType(Init->getTypeSourceInfo(), TemplateArgs, Init->getSourceLocation(), New->getDeclName()); if (!BaseTInfo) { AnyErrors = true; break; } // Build the initializer. MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(), BaseTInfo, TempInit.get(), New->getParent(), SourceLocation()); if (NewInit.isInvalid()) { AnyErrors = true; break; } NewInits.push_back(NewInit.get()); } continue; } // Instantiate the initializer. ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs, /*CXXDirectInit=*/true); if (TempInit.isInvalid()) { AnyErrors = true; continue; } MemInitResult NewInit; if (Init->isDelegatingInitializer() || Init->isBaseInitializer()) { TypeSourceInfo *TInfo = SubstType(Init->getTypeSourceInfo(), TemplateArgs, Init->getSourceLocation(), New->getDeclName()); if (!TInfo) { AnyErrors = true; New->setInvalidDecl(); continue; } if (Init->isBaseInitializer()) NewInit = BuildBaseInitializer(TInfo->getType(), TInfo, TempInit.get(), New->getParent(), EllipsisLoc); else NewInit = BuildDelegatingInitializer(TInfo, TempInit.get(), cast(CurContext->getParent())); } else if (Init->isMemberInitializer()) { FieldDecl *Member = cast_or_null(FindInstantiatedDecl( Init->getMemberLocation(), Init->getMember(), TemplateArgs)); if (!Member) { AnyErrors = true; New->setInvalidDecl(); continue; } NewInit = BuildMemberInitializer(Member, TempInit.get(), Init->getSourceLocation()); } else if (Init->isIndirectMemberInitializer()) { IndirectFieldDecl *IndirectMember = cast_or_null(FindInstantiatedDecl( Init->getMemberLocation(), Init->getIndirectMember(), TemplateArgs)); if (!IndirectMember) { AnyErrors = true; New->setInvalidDecl(); continue; } NewInit = BuildMemberInitializer(IndirectMember, TempInit.get(), Init->getSourceLocation()); } if (NewInit.isInvalid()) { AnyErrors = true; New->setInvalidDecl(); } else { NewInits.push_back(NewInit.get()); } } // Assign all the initializers to the new constructor. ActOnMemInitializers(New, /*FIXME: ColonLoc */ SourceLocation(), NewInits, AnyErrors); } // TODO: this could be templated if the various decl types used the // same method name. static bool isInstantiationOf(ClassTemplateDecl *Pattern, ClassTemplateDecl *Instance) { Pattern = Pattern->getCanonicalDecl(); do { Instance = Instance->getCanonicalDecl(); if (Pattern == Instance) return true; Instance = Instance->getInstantiatedFromMemberTemplate(); } while (Instance); return false; } static bool isInstantiationOf(FunctionTemplateDecl *Pattern, FunctionTemplateDecl *Instance) { Pattern = Pattern->getCanonicalDecl(); do { Instance = Instance->getCanonicalDecl(); if (Pattern == Instance) return true; Instance = Instance->getInstantiatedFromMemberTemplate(); } while (Instance); return false; } static bool isInstantiationOf(ClassTemplatePartialSpecializationDecl *Pattern, ClassTemplatePartialSpecializationDecl *Instance) { Pattern = cast(Pattern->getCanonicalDecl()); do { Instance = cast( Instance->getCanonicalDecl()); if (Pattern == Instance) return true; Instance = Instance->getInstantiatedFromMember(); } while (Instance); return false; } static bool isInstantiationOf(CXXRecordDecl *Pattern, CXXRecordDecl *Instance) { Pattern = Pattern->getCanonicalDecl(); do { Instance = Instance->getCanonicalDecl(); if (Pattern == Instance) return true; Instance = Instance->getInstantiatedFromMemberClass(); } while (Instance); return false; } static bool isInstantiationOf(FunctionDecl *Pattern, FunctionDecl *Instance) { Pattern = Pattern->getCanonicalDecl(); do { Instance = Instance->getCanonicalDecl(); if (Pattern == Instance) return true; Instance = Instance->getInstantiatedFromMemberFunction(); } while (Instance); return false; } static bool isInstantiationOf(EnumDecl *Pattern, EnumDecl *Instance) { Pattern = Pattern->getCanonicalDecl(); do { Instance = Instance->getCanonicalDecl(); if (Pattern == Instance) return true; Instance = Instance->getInstantiatedFromMemberEnum(); } while (Instance); return false; } static bool isInstantiationOf(UsingShadowDecl *Pattern, UsingShadowDecl *Instance, ASTContext &C) { return declaresSameEntity(C.getInstantiatedFromUsingShadowDecl(Instance), Pattern); } static bool isInstantiationOf(UsingDecl *Pattern, UsingDecl *Instance, ASTContext &C) { return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance), Pattern); } template static bool isInstantiationOfUnresolvedUsingDecl(T *Pattern, Decl *Other, ASTContext &Ctx) { // An unresolved using declaration can instantiate to an unresolved using // declaration, or to a using declaration or a using declaration pack. // // Multiple declarations can claim to be instantiated from an unresolved // using declaration if it's a pack expansion. We want the UsingPackDecl // in that case, not the individual UsingDecls within the pack. bool OtherIsPackExpansion; NamedDecl *OtherFrom; if (auto *OtherUUD = dyn_cast(Other)) { OtherIsPackExpansion = OtherUUD->isPackExpansion(); OtherFrom = Ctx.getInstantiatedFromUsingDecl(OtherUUD); } else if (auto *OtherUPD = dyn_cast(Other)) { OtherIsPackExpansion = true; OtherFrom = OtherUPD->getInstantiatedFromUsingDecl(); } else if (auto *OtherUD = dyn_cast(Other)) { OtherIsPackExpansion = false; OtherFrom = Ctx.getInstantiatedFromUsingDecl(OtherUD); } else { return false; } return Pattern->isPackExpansion() == OtherIsPackExpansion && declaresSameEntity(OtherFrom, Pattern); } static bool isInstantiationOfStaticDataMember(VarDecl *Pattern, VarDecl *Instance) { assert(Instance->isStaticDataMember()); Pattern = Pattern->getCanonicalDecl(); do { Instance = Instance->getCanonicalDecl(); if (Pattern == Instance) return true; Instance = Instance->getInstantiatedFromStaticDataMember(); } while (Instance); return false; } // Other is the prospective instantiation // D is the prospective pattern static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) { if (auto *UUD = dyn_cast(D)) return isInstantiationOfUnresolvedUsingDecl(UUD, Other, Ctx); if (auto *UUD = dyn_cast(D)) return isInstantiationOfUnresolvedUsingDecl(UUD, Other, Ctx); if (D->getKind() != Other->getKind()) return false; if (auto *Record = dyn_cast(Other)) return isInstantiationOf(cast(D), Record); if (auto *Function = dyn_cast(Other)) return isInstantiationOf(cast(D), Function); if (auto *Enum = dyn_cast(Other)) return isInstantiationOf(cast(D), Enum); if (auto *Var = dyn_cast(Other)) if (Var->isStaticDataMember()) return isInstantiationOfStaticDataMember(cast(D), Var); if (auto *Temp = dyn_cast(Other)) return isInstantiationOf(cast(D), Temp); if (auto *Temp = dyn_cast(Other)) return isInstantiationOf(cast(D), Temp); if (auto *PartialSpec = dyn_cast(Other)) return isInstantiationOf(cast(D), PartialSpec); if (auto *Field = dyn_cast(Other)) { if (!Field->getDeclName()) { // This is an unnamed field. return declaresSameEntity(Ctx.getInstantiatedFromUnnamedFieldDecl(Field), cast(D)); } } if (auto *Using = dyn_cast(Other)) return isInstantiationOf(cast(D), Using, Ctx); if (auto *Shadow = dyn_cast(Other)) return isInstantiationOf(cast(D), Shadow, Ctx); return D->getDeclName() && D->getDeclName() == cast(Other)->getDeclName(); } template static NamedDecl *findInstantiationOf(ASTContext &Ctx, NamedDecl *D, ForwardIterator first, ForwardIterator last) { for (; first != last; ++first) if (isInstantiationOf(Ctx, D, *first)) return cast(*first); return nullptr; } /// \brief Finds the instantiation of the given declaration context /// within the current instantiation. /// /// \returns NULL if there was an error DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC, const MultiLevelTemplateArgumentList &TemplateArgs) { if (NamedDecl *D = dyn_cast(DC)) { Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs, true); return cast_or_null(ID); } else return DC; } /// \brief Find the instantiation of the given declaration within the /// current instantiation. /// /// This routine is intended to be used when \p D is a declaration /// referenced from within a template, that needs to mapped into the /// corresponding declaration within an instantiation. For example, /// given: /// /// \code /// template /// struct X { /// enum Kind { /// KnownValue = sizeof(T) /// }; /// /// bool getKind() const { return KnownValue; } /// }; /// /// template struct X; /// \endcode /// /// In the instantiation of X::getKind(), we need to map the /// \p EnumConstantDecl for \p KnownValue (which refers to /// X::::KnownValue) to its instantiation /// (X::::KnownValue). \p FindInstantiatedDecl performs /// this mapping from within the instantiation of X. NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs, bool FindingInstantiatedContext) { DeclContext *ParentDC = D->getDeclContext(); // FIXME: Parmeters of pointer to functions (y below) that are themselves // parameters (p below) can have their ParentDC set to the translation-unit // - thus we can not consistently check if the ParentDC of such a parameter // is Dependent or/and a FunctionOrMethod. // For e.g. this code, during Template argument deduction tries to // find an instantiated decl for (T y) when the ParentDC for y is // the translation unit. // e.g. template void Foo(auto (*p)(T y) -> decltype(y())) {} // float baz(float(*)()) { return 0.0; } // Foo(baz); // The better fix here is perhaps to ensure that a ParmVarDecl, by the time // it gets here, always has a FunctionOrMethod as its ParentDC?? // For now: // - as long as we have a ParmVarDecl whose parent is non-dependent and // whose type is not instantiation dependent, do nothing to the decl // - otherwise find its instantiated decl. if (isa(D) && !ParentDC->isDependentContext() && !cast(D)->getType()->isInstantiationDependentType()) return D; if (isa(D) || isa(D) || isa(D) || isa(D) || (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) || (isa(D) && cast(D)->isLambda())) { // D is a local of some kind. Look into the map of local // declarations to their instantiations. if (CurrentInstantiationScope) { if (auto Found = CurrentInstantiationScope->findInstantiationOf(D)) { if (Decl *FD = Found->dyn_cast()) return cast(FD); int PackIdx = ArgumentPackSubstitutionIndex; assert(PackIdx != -1 && "found declaration pack but not pack expanding"); typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; return cast((*Found->get())[PackIdx]); } } // If we're performing a partial substitution during template argument // deduction, we may not have values for template parameters yet. They // just map to themselves. if (isa(D) || isa(D) || isa(D)) return D; if (D->isInvalidDecl()) return nullptr; // Normally this function only searches for already instantiated declaration // however we have to make an exclusion for local types used before // definition as in the code: // // template void f1() { // void g1(struct x1); // struct x1 {}; // } // // In this case instantiation of the type of 'g1' requires definition of // 'x1', which is defined later. Error recovery may produce an enum used // before definition. In these cases we need to instantiate relevant // declarations here. bool NeedInstantiate = false; if (CXXRecordDecl *RD = dyn_cast(D)) NeedInstantiate = RD->isLocalClass(); else NeedInstantiate = isa(D); if (NeedInstantiate) { Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); CurrentInstantiationScope->InstantiatedLocal(D, Inst); return cast(Inst); } // If we didn't find the decl, then we must have a label decl that hasn't // been found yet. Lazily instantiate it and return it now. assert(isa(D)); Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); assert(Inst && "Failed to instantiate label??"); CurrentInstantiationScope->InstantiatedLocal(D, Inst); return cast(Inst); } // For variable template specializations, update those that are still // type-dependent. if (VarTemplateSpecializationDecl *VarSpec = dyn_cast(D)) { bool InstantiationDependent = false; const TemplateArgumentListInfo &VarTemplateArgs = VarSpec->getTemplateArgsInfo(); if (TemplateSpecializationType::anyDependentTemplateArguments( VarTemplateArgs, InstantiationDependent)) D = cast( SubstDecl(D, VarSpec->getDeclContext(), TemplateArgs)); return D; } if (CXXRecordDecl *Record = dyn_cast(D)) { if (!Record->isDependentContext()) return D; // Determine whether this record is the "templated" declaration describing // a class template or class template partial specialization. ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate(); if (ClassTemplate) ClassTemplate = ClassTemplate->getCanonicalDecl(); else if (ClassTemplatePartialSpecializationDecl *PartialSpec = dyn_cast(Record)) ClassTemplate = PartialSpec->getSpecializedTemplate()->getCanonicalDecl(); // Walk the current context to find either the record or an instantiation of // it. DeclContext *DC = CurContext; while (!DC->isFileContext()) { // If we're performing substitution while we're inside the template // definition, we'll find our own context. We're done. if (DC->Equals(Record)) return Record; if (CXXRecordDecl *InstRecord = dyn_cast(DC)) { // Check whether we're in the process of instantiating a class template // specialization of the template we're mapping. if (ClassTemplateSpecializationDecl *InstSpec = dyn_cast(InstRecord)){ ClassTemplateDecl *SpecTemplate = InstSpec->getSpecializedTemplate(); if (ClassTemplate && isInstantiationOf(ClassTemplate, SpecTemplate)) return InstRecord; } // Check whether we're in the process of instantiating a member class. if (isInstantiationOf(Record, InstRecord)) return InstRecord; } // Move to the outer template scope. if (FunctionDecl *FD = dyn_cast(DC)) { if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){ DC = FD->getLexicalDeclContext(); continue; } // An implicit deduction guide acts as if it's within the class template // specialization described by its name and first N template params. auto *Guide = dyn_cast(FD); if (Guide && Guide->isImplicit()) { TemplateDecl *TD = Guide->getDeducedTemplate(); // Convert the arguments to an "as-written" list. TemplateArgumentListInfo Args(Loc, Loc); for (TemplateArgument Arg : TemplateArgs.getInnermost().take_front( TD->getTemplateParameters()->size())) { ArrayRef Unpacked(Arg); if (Arg.getKind() == TemplateArgument::Pack) Unpacked = Arg.pack_elements(); for (TemplateArgument UnpackedArg : Unpacked) Args.addArgument( getTrivialTemplateArgumentLoc(UnpackedArg, QualType(), Loc)); } QualType T = CheckTemplateIdType(TemplateName(TD), Loc, Args); if (T.isNull()) return nullptr; auto *SubstRecord = T->getAsCXXRecordDecl(); assert(SubstRecord && "class template id not a class type?"); // Check that this template-id names the primary template and not a // partial or explicit specialization. (In the latter cases, it's // meaningless to attempt to find an instantiation of D within the // specialization.) // FIXME: The standard doesn't say what should happen here. if (FindingInstantiatedContext && usesPartialOrExplicitSpecialization( Loc, cast(SubstRecord))) { Diag(Loc, diag::err_specialization_not_primary_template) << T << (SubstRecord->getTemplateSpecializationKind() == TSK_ExplicitSpecialization); return nullptr; } DC = SubstRecord; continue; } } DC = DC->getParent(); } // Fall through to deal with other dependent record types (e.g., // anonymous unions in class templates). } if (!ParentDC->isDependentContext()) return D; ParentDC = FindInstantiatedContext(Loc, ParentDC, TemplateArgs); if (!ParentDC) return nullptr; if (ParentDC != D->getDeclContext()) { // We performed some kind of instantiation in the parent context, // so now we need to look into the instantiated parent context to // find the instantiation of the declaration D. // If our context used to be dependent, we may need to instantiate // it before performing lookup into that context. bool IsBeingInstantiated = false; if (CXXRecordDecl *Spec = dyn_cast(ParentDC)) { if (!Spec->isDependentContext()) { QualType T = Context.getTypeDeclType(Spec); const RecordType *Tag = T->getAs(); assert(Tag && "type of non-dependent record is not a RecordType"); if (Tag->isBeingDefined()) IsBeingInstantiated = true; if (!Tag->isBeingDefined() && RequireCompleteType(Loc, T, diag::err_incomplete_type)) return nullptr; ParentDC = Tag->getDecl(); } } NamedDecl *Result = nullptr; // FIXME: If the name is a dependent name, this lookup won't necessarily // find it. Does that ever matter? if (auto Name = D->getDeclName()) { DeclarationNameInfo NameInfo(Name, D->getLocation()); Name = SubstDeclarationNameInfo(NameInfo, TemplateArgs).getName(); if (!Name) return nullptr; DeclContext::lookup_result Found = ParentDC->lookup(Name); Result = findInstantiationOf(Context, D, Found.begin(), Found.end()); } else { // Since we don't have a name for the entity we're looking for, // our only option is to walk through all of the declarations to // find that name. This will occur in a few cases: // // - anonymous struct/union within a template // - unnamed class/struct/union/enum within a template // // FIXME: Find a better way to find these instantiations! Result = findInstantiationOf(Context, D, ParentDC->decls_begin(), ParentDC->decls_end()); } if (!Result) { if (isa(D)) { // UsingShadowDecls can instantiate to nothing because of using hiding. } else if (Diags.hasErrorOccurred()) { // We've already complained about something, so most likely this // declaration failed to instantiate. There's no point in complaining // further, since this is normal in invalid code. } else if (IsBeingInstantiated) { // The class in which this member exists is currently being // instantiated, and we haven't gotten around to instantiating this // member yet. This can happen when the code uses forward declarations // of member classes, and introduces ordering dependencies via // template instantiation. Diag(Loc, diag::err_member_not_yet_instantiated) << D->getDeclName() << Context.getTypeDeclType(cast(ParentDC)); Diag(D->getLocation(), diag::note_non_instantiated_member_here); } else if (EnumConstantDecl *ED = dyn_cast(D)) { // This enumeration constant was found when the template was defined, // but can't be found in the instantiation. This can happen if an // unscoped enumeration member is explicitly specialized. EnumDecl *Enum = cast(ED->getLexicalDeclContext()); EnumDecl *Spec = cast(FindInstantiatedDecl(Loc, Enum, TemplateArgs)); assert(Spec->getTemplateSpecializationKind() == TSK_ExplicitSpecialization); Diag(Loc, diag::err_enumerator_does_not_exist) << D->getDeclName() << Context.getTypeDeclType(cast(Spec->getDeclContext())); Diag(Spec->getLocation(), diag::note_enum_specialized_here) << Context.getTypeDeclType(Spec); } else { // We should have found something, but didn't. llvm_unreachable("Unable to find instantiation of declaration!"); } } D = Result; } return D; } /// \brief Performs template instantiation for all implicit template /// instantiations we have seen until this point. void Sema::PerformPendingInstantiations(bool LocalOnly) { while (!PendingLocalImplicitInstantiations.empty() || (!LocalOnly && !PendingInstantiations.empty())) { PendingImplicitInstantiation Inst; if (PendingLocalImplicitInstantiations.empty()) { Inst = PendingInstantiations.front(); PendingInstantiations.pop_front(); } else { Inst = PendingLocalImplicitInstantiations.front(); PendingLocalImplicitInstantiations.pop_front(); } // Instantiate function definitions if (FunctionDecl *Function = dyn_cast(Inst.first)) { bool DefinitionRequired = Function->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true, DefinitionRequired, true); if (Function->isDefined()) Function->setInstantiationIsPending(false); continue; } // Instantiate variable definitions VarDecl *Var = cast(Inst.first); assert((Var->isStaticDataMember() || isa(Var)) && "Not a static data member, nor a variable template" " specialization?"); // Don't try to instantiate declarations if the most recent redeclaration // is invalid. if (Var->getMostRecentDecl()->isInvalidDecl()) continue; // Check if the most recent declaration has changed the specialization kind // and removed the need for implicit instantiation. switch (Var->getMostRecentDecl()->getTemplateSpecializationKind()) { case TSK_Undeclared: llvm_unreachable("Cannot instantitiate an undeclared specialization."); case TSK_ExplicitInstantiationDeclaration: case TSK_ExplicitSpecialization: continue; // No longer need to instantiate this type. case TSK_ExplicitInstantiationDefinition: // We only need an instantiation if the pending instantiation *is* the // explicit instantiation. if (Var != Var->getMostRecentDecl()) continue; case TSK_ImplicitInstantiation: break; } PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(), "instantiating variable definition"); bool DefinitionRequired = Var->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; // Instantiate static data member definitions or variable template // specializations. InstantiateVariableDefinition(/*FIXME:*/ Inst.second, Var, true, DefinitionRequired, true); } } void Sema::PerformDependentDiagnostics(const DeclContext *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs) { for (auto DD : Pattern->ddiags()) { switch (DD->getKind()) { case DependentDiagnostic::Access: HandleDependentAccessCheck(*DD, TemplateArgs); break; } } } Index: head/contrib/llvm/tools/clang =================================================================== --- head/contrib/llvm/tools/clang (revision 326908) +++ head/contrib/llvm/tools/clang (revision 326909) Property changes on: head/contrib/llvm/tools/clang ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /vendor/clang/dist:r326471-326907 Index: head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler.h =================================================================== --- head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler.h (revision 326908) +++ head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler.h (revision 326909) @@ -1,319 +1,323 @@ //===- lib/FileFormat/MachO/ArchHandler.h ---------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_READER_WRITER_MACHO_ARCH_HANDLER_H #define LLD_READER_WRITER_MACHO_ARCH_HANDLER_H #include "Atoms.h" #include "File.h" #include "MachONormalizedFile.h" #include "lld/Core/LLVM.h" #include "lld/Core/Error.h" #include "lld/Core/Reference.h" #include "lld/Core/Simple.h" #include "lld/ReaderWriter/MachOLinkingContext.h" #include "llvm/ADT/Triple.h" namespace lld { namespace mach_o { /// /// The ArchHandler class handles all architecture specific aspects of /// mach-o linking. /// class ArchHandler { public: virtual ~ArchHandler(); /// There is no public interface to subclasses of ArchHandler, so this /// is the only way to instantiate an ArchHandler. static std::unique_ptr create(MachOLinkingContext::Arch arch); /// Get (arch specific) kind strings used by Registry. virtual const Registry::KindStrings *kindStrings() = 0; /// Convert mach-o Arch to Reference::KindArch. virtual Reference::KindArch kindArch() = 0; /// Used by StubPass to update References to shared library functions /// to be references to a stub. virtual bool isCallSite(const Reference &) = 0; /// Used by GOTPass to locate GOT References virtual bool isGOTAccess(const Reference &, bool &canBypassGOT) { return false; } /// Used by TLVPass to locate TLV References. virtual bool isTLVAccess(const Reference &) const { return false; } /// Used by the TLVPass to update TLV References. virtual void updateReferenceToTLV(const Reference *) {} /// Used by ShimPass to insert shims in branches that switch mode. virtual bool isNonCallBranch(const Reference &) = 0; /// Used by GOTPass to update GOT References virtual void updateReferenceToGOT(const Reference *, bool targetIsNowGOT) {} /// Does this architecture make use of __unwind_info sections for exception /// handling? If so, it will need a separate pass to create them. virtual bool needsCompactUnwind() = 0; /// Returns the kind of reference to use to synthesize a 32-bit image-offset /// value, used in the __unwind_info section. virtual Reference::KindValue imageOffsetKind() = 0; /// Returns the kind of reference to use to synthesize a 32-bit image-offset /// indirect value. Used for personality functions in the __unwind_info /// section. virtual Reference::KindValue imageOffsetKindIndirect() = 0; /// Architecture specific compact unwind type that signals __eh_frame should /// actually be used. virtual uint32_t dwarfCompactUnwindType() = 0; /// Reference from an __eh_frame CIE atom to its personality function it's /// describing. Usually pointer-sized and PC-relative, but differs in whether /// it needs to be in relocatable objects. virtual Reference::KindValue unwindRefToPersonalityFunctionKind() = 0; /// Reference from an __eh_frame FDE to the CIE it's based on. virtual Reference::KindValue unwindRefToCIEKind() = 0; /// Reference from an __eh_frame FDE atom to the function it's /// describing. Usually pointer-sized and PC-relative, but differs in whether /// it needs to be in relocatable objects. virtual Reference::KindValue unwindRefToFunctionKind() = 0; /// Reference from an __unwind_info entry of dwarfCompactUnwindType to the /// required __eh_frame entry. On current architectures, the low 24 bits /// represent the offset of the function's FDE entry from the start of /// __eh_frame. virtual Reference::KindValue unwindRefToEhFrameKind() = 0; /// Returns a pointer sized reference kind. On 64-bit targets this will /// likely be something like pointer64, and pointer32 on 32-bit targets. virtual Reference::KindValue pointerKind() = 0; virtual const Atom *fdeTargetFunction(const DefinedAtom *fde); /// Used by normalizedFromAtoms() to know where to generated rebasing and /// binding info in final executables. virtual bool isPointer(const Reference &) = 0; /// Used by normalizedFromAtoms() to know where to generated lazy binding /// info in final executables. virtual bool isLazyPointer(const Reference &); + /// Reference from an __stub_helper entry to the required offset of the + /// lazy bind commands. + virtual Reference::KindValue lazyImmediateLocationKind() = 0; + /// Returns true if the specified relocation is paired to the next relocation. virtual bool isPairedReloc(const normalized::Relocation &) = 0; /// Prototype for a helper function. Given a sectionIndex and address, /// finds the atom and offset with that atom of that address. typedef std::function FindAtomBySectionAndAddress; /// Prototype for a helper function. Given a symbolIndex, finds the atom /// representing that symbol. typedef std::function FindAtomBySymbolIndex; /// Analyzes a relocation from a .o file and returns the info /// (kind, target, addend) needed to instantiate a Reference. /// Two helper functions are passed as parameters to find the target atom /// given a symbol index or address. virtual llvm::Error getReferenceInfo(const normalized::Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool isBigEndian, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) = 0; /// Analyzes a pair of relocations from a .o file and returns the info /// (kind, target, addend) needed to instantiate a Reference. /// Two helper functions are passed as parameters to find the target atom /// given a symbol index or address. virtual llvm::Error getPairReferenceInfo(const normalized::Relocation &reloc1, const normalized::Relocation &reloc2, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool isBig, bool scatterable, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) = 0; /// Prototype for a helper function. Given an atom, finds the symbol table /// index for it in the output file. typedef std::function FindSymbolIndexForAtom; /// Prototype for a helper function. Given an atom, finds the index /// of the section that will contain the atom. typedef std::function FindSectionIndexForAtom; /// Prototype for a helper function. Given an atom, finds the address /// assigned to it in the output file. typedef std::function FindAddressForAtom; /// Some architectures require local symbols on anonymous atoms. virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) { return false; } /// Copy raw content then apply all fixup References on an Atom. virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress, FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress, llvm::MutableArrayRef atomContentBuffer) = 0; /// Used in -r mode to convert a Reference to a mach-o relocation. virtual void appendSectionRelocations(const DefinedAtom &atom, uint64_t atomSectionOffset, const Reference &ref, FindSymbolIndexForAtom, FindSectionIndexForAtom, FindAddressForAtom, normalized::Relocations&) = 0; /// Add arch-specific References. virtual void addAdditionalReferences(MachODefinedAtom &atom) { } // Add Reference for data-in-code marker. virtual void addDataInCodeReference(MachODefinedAtom &atom, uint32_t atomOff, uint16_t length, uint16_t kind) { } /// Returns true if the specificed Reference value marks the start or end /// of a data-in-code range in an atom. virtual bool isDataInCodeTransition(Reference::KindValue refKind) { return false; } /// Returns the Reference value for a Reference that marks that start of /// a data-in-code range. virtual Reference::KindValue dataInCodeTransitionStart( const MachODefinedAtom &atom) { return 0; } /// Returns the Reference value for a Reference that marks that end of /// a data-in-code range. virtual Reference::KindValue dataInCodeTransitionEnd( const MachODefinedAtom &atom) { return 0; } /// Only relevant for 32-bit arm archs. virtual bool isThumbFunction(const DefinedAtom &atom) { return false; } /// Only relevant for 32-bit arm archs. virtual const DefinedAtom *createShim(MachOFile &file, bool thumbToArm, const DefinedAtom &) { llvm_unreachable("shims only support on arm"); } /// Does a given unwind-cfi atom represent a CIE (as opposed to an FDE). static bool isDwarfCIE(bool isBig, const DefinedAtom *atom); struct ReferenceInfo { Reference::KindArch arch; uint16_t kind; uint32_t offset; int32_t addend; }; struct OptionalRefInfo { bool used; uint16_t kind; uint32_t offset; int32_t addend; }; /// Table of architecture specific information for creating stubs. struct StubInfo { const char* binderSymbolName; ReferenceInfo lazyPointerReferenceToHelper; ReferenceInfo lazyPointerReferenceToFinal; ReferenceInfo nonLazyPointerReferenceToBinder; uint8_t codeAlignment; uint32_t stubSize; uint8_t stubBytes[16]; ReferenceInfo stubReferenceToLP; OptionalRefInfo optStubReferenceToLP; uint32_t stubHelperSize; uint8_t stubHelperBytes[16]; ReferenceInfo stubHelperReferenceToImm; ReferenceInfo stubHelperReferenceToHelperCommon; DefinedAtom::ContentType stubHelperImageCacheContentType; uint32_t stubHelperCommonSize; uint8_t stubHelperCommonAlignment; uint8_t stubHelperCommonBytes[36]; ReferenceInfo stubHelperCommonReferenceToCache; OptionalRefInfo optStubHelperCommonReferenceToCache; ReferenceInfo stubHelperCommonReferenceToBinder; OptionalRefInfo optStubHelperCommonReferenceToBinder; }; virtual const StubInfo &stubInfo() = 0; protected: ArchHandler(); static std::unique_ptr create_x86_64(); static std::unique_ptr create_x86(); static std::unique_ptr create_arm(); static std::unique_ptr create_arm64(); // Handy way to pack mach-o r_type and other bit fields into one 16-bit value. typedef uint16_t RelocPattern; enum { rScattered = 0x8000, rPcRel = 0x4000, rExtern = 0x2000, rLength1 = 0x0000, rLength2 = 0x0100, rLength4 = 0x0200, rLength8 = 0x0300, rLenArmLo = rLength1, rLenArmHi = rLength2, rLenThmbLo = rLength4, rLenThmbHi = rLength8 }; /// Extract RelocPattern from normalized mach-o relocation. static RelocPattern relocPattern(const normalized::Relocation &reloc); /// Create normalized Relocation initialized from pattern. static normalized::Relocation relocFromPattern(RelocPattern pattern); /// One liner to add a relocation. static void appendReloc(normalized::Relocations &relocs, uint32_t offset, uint32_t symbol, uint32_t value, RelocPattern pattern); static int16_t readS16(const uint8_t *addr, bool isBig); static int32_t readS32(const uint8_t *addr, bool isBig); static uint32_t readU32(const uint8_t *addr, bool isBig); static int64_t readS64(const uint8_t *addr, bool isBig); }; } // namespace mach_o } // namespace lld #endif // LLD_READER_WRITER_MACHO_ARCH_HANDLER_H Index: head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp =================================================================== --- head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp (revision 326908) +++ head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp (revision 326909) @@ -1,1519 +1,1523 @@ //===- lib/FileFormat/MachO/ArchHandler_arm.cpp ---------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "ArchHandler.h" #include "Atoms.h" #include "MachONormalizedFileBinaryUtils.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm::MachO; using namespace lld::mach_o::normalized; namespace lld { namespace mach_o { using llvm::support::ulittle32_t; using llvm::support::little32_t; class ArchHandler_arm : public ArchHandler { public: ArchHandler_arm() = default; ~ArchHandler_arm() override = default; const Registry::KindStrings *kindStrings() override { return _sKindStrings; } Reference::KindArch kindArch() override { return Reference::KindArch::ARM; } const ArchHandler::StubInfo &stubInfo() override; bool isCallSite(const Reference &) override; bool isPointer(const Reference &) override; bool isPairedReloc(const normalized::Relocation &) override; bool isNonCallBranch(const Reference &) override; bool needsCompactUnwind() override { return false; } Reference::KindValue imageOffsetKind() override { return invalid; } Reference::KindValue imageOffsetKindIndirect() override { return invalid; } Reference::KindValue unwindRefToPersonalityFunctionKind() override { return invalid; } Reference::KindValue unwindRefToCIEKind() override { return invalid; } Reference::KindValue unwindRefToFunctionKind() override { return invalid; } Reference::KindValue unwindRefToEhFrameKind() override { return invalid; } + Reference::KindValue lazyImmediateLocationKind() override { + return lazyImmediateLocation; + } + Reference::KindValue pointerKind() override { return invalid; } uint32_t dwarfCompactUnwindType() override { // FIXME return -1; } llvm::Error getReferenceInfo(const normalized::Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool swap, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) override; llvm::Error getPairReferenceInfo(const normalized::Relocation &reloc1, const normalized::Relocation &reloc2, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool swap, bool scatterable, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) override; void generateAtomContent(const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress, FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress, llvm::MutableArrayRef atomContentBuffer) override; void appendSectionRelocations(const DefinedAtom &atom, uint64_t atomSectionOffset, const Reference &ref, FindSymbolIndexForAtom, FindSectionIndexForAtom, FindAddressForAtom, normalized::Relocations &) override; void addAdditionalReferences(MachODefinedAtom &atom) override; bool isDataInCodeTransition(Reference::KindValue refKind) override { switch (refKind) { case modeThumbCode: case modeArmCode: case modeData: return true; default: return false; break; } } Reference::KindValue dataInCodeTransitionStart( const MachODefinedAtom &atom) override { return modeData; } Reference::KindValue dataInCodeTransitionEnd( const MachODefinedAtom &atom) override { return atom.isThumb() ? modeThumbCode : modeArmCode; } bool isThumbFunction(const DefinedAtom &atom) override; const DefinedAtom *createShim(MachOFile &file, bool thumbToArm, const DefinedAtom &) override; private: friend class Thumb2ToArmShimAtom; friend class ArmToThumbShimAtom; static const Registry::KindStrings _sKindStrings[]; static const StubInfo _sStubInfoArmPIC; enum ArmKind : Reference::KindValue { invalid, /// for error condition modeThumbCode, /// Content starting at this offset is thumb. modeArmCode, /// Content starting at this offset is arm. modeData, /// Content starting at this offset is data. // Kinds found in mach-o .o files: thumb_bl22, /// ex: bl _foo thumb_b22, /// ex: b _foo thumb_movw, /// ex: movw r1, :lower16:_foo thumb_movt, /// ex: movt r1, :lower16:_foo thumb_movw_funcRel, /// ex: movw r1, :lower16:(_foo-(L1+4)) thumb_movt_funcRel, /// ex: movt r1, :upper16:(_foo-(L1+4)) arm_bl24, /// ex: bl _foo arm_b24, /// ex: b _foo arm_movw, /// ex: movw r1, :lower16:_foo arm_movt, /// ex: movt r1, :lower16:_foo arm_movw_funcRel, /// ex: movw r1, :lower16:(_foo-(L1+4)) arm_movt_funcRel, /// ex: movt r1, :upper16:(_foo-(L1+4)) pointer32, /// ex: .long _foo delta32, /// ex: .long _foo - . // Kinds introduced by Passes: lazyPointer, /// Location contains a lazy pointer. lazyImmediateLocation, /// Location contains immediate value used in stub. }; // Utility functions for inspecting/updating instructions. static bool isThumbMovw(uint32_t instruction); static bool isThumbMovt(uint32_t instruction); static bool isArmMovw(uint32_t instruction); static bool isArmMovt(uint32_t instruction); static int32_t getDisplacementFromThumbBranch(uint32_t instruction, uint32_t); static int32_t getDisplacementFromArmBranch(uint32_t instruction); static uint16_t getWordFromThumbMov(uint32_t instruction); static uint16_t getWordFromArmMov(uint32_t instruction); static uint32_t clearThumbBit(uint32_t value, const Atom *target); static uint32_t setDisplacementInArmBranch(uint32_t instr, int32_t disp, bool targetIsThumb); static uint32_t setDisplacementInThumbBranch(uint32_t instr, uint32_t ia, int32_t disp, bool targetThumb); static uint32_t setWordFromThumbMov(uint32_t instruction, uint16_t word); static uint32_t setWordFromArmMov(uint32_t instruction, uint16_t word); StringRef stubName(const DefinedAtom &); bool useExternalRelocationTo(const Atom &target); void applyFixupFinal(const Reference &ref, uint8_t *location, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress, bool &thumbMode, bool targetIsThumb); void applyFixupRelocatable(const Reference &ref, uint8_t *location, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress, bool &thumbMode, bool targetIsThumb); }; //===----------------------------------------------------------------------===// // ArchHandler_arm //===----------------------------------------------------------------------===// const Registry::KindStrings ArchHandler_arm::_sKindStrings[] = { LLD_KIND_STRING_ENTRY(invalid), LLD_KIND_STRING_ENTRY(modeThumbCode), LLD_KIND_STRING_ENTRY(modeArmCode), LLD_KIND_STRING_ENTRY(modeData), LLD_KIND_STRING_ENTRY(thumb_bl22), LLD_KIND_STRING_ENTRY(thumb_b22), LLD_KIND_STRING_ENTRY(thumb_movw), LLD_KIND_STRING_ENTRY(thumb_movt), LLD_KIND_STRING_ENTRY(thumb_movw_funcRel), LLD_KIND_STRING_ENTRY(thumb_movt_funcRel), LLD_KIND_STRING_ENTRY(arm_bl24), LLD_KIND_STRING_ENTRY(arm_b24), LLD_KIND_STRING_ENTRY(arm_movw), LLD_KIND_STRING_ENTRY(arm_movt), LLD_KIND_STRING_ENTRY(arm_movw_funcRel), LLD_KIND_STRING_ENTRY(arm_movt_funcRel), LLD_KIND_STRING_ENTRY(pointer32), LLD_KIND_STRING_ENTRY(delta32), LLD_KIND_STRING_ENTRY(lazyPointer), LLD_KIND_STRING_ENTRY(lazyImmediateLocation), LLD_KIND_STRING_END }; const ArchHandler::StubInfo ArchHandler_arm::_sStubInfoArmPIC = { "dyld_stub_binder", // References in lazy pointer { Reference::KindArch::ARM, pointer32, 0, 0 }, { Reference::KindArch::ARM, lazyPointer, 0, 0 }, // GOT pointer to dyld_stub_binder { Reference::KindArch::ARM, pointer32, 0, 0 }, // arm code alignment 2^2 2, // Stub size and code 16, { 0x04, 0xC0, 0x9F, 0xE5, // ldr ip, pc + 12 0x0C, 0xC0, 0x8F, 0xE0, // add ip, pc, ip 0x00, 0xF0, 0x9C, 0xE5, // ldr pc, [ip] 0x00, 0x00, 0x00, 0x00 }, // .long L_foo$lazy_ptr - (L1$scv + 8) { Reference::KindArch::ARM, delta32, 12, 0 }, { false, 0, 0, 0 }, // Stub Helper size and code 12, { 0x00, 0xC0, 0x9F, 0xE5, // ldr ip, [pc, #0] 0x00, 0x00, 0x00, 0xEA, // b _helperhelper 0x00, 0x00, 0x00, 0x00 }, // .long lazy-info-offset { Reference::KindArch::ARM, lazyImmediateLocation, 8, 0 }, { Reference::KindArch::ARM, arm_b24, 4, 0 }, // Stub helper image cache content type DefinedAtom::typeGOT, // Stub Helper-Common size and code 36, // Stub helper alignment 2, { // push lazy-info-offset 0x04, 0xC0, 0x2D, 0xE5, // str ip, [sp, #-4]! // push address of dyld_mageLoaderCache 0x10, 0xC0, 0x9F, 0xE5, // ldr ip, L1 0x0C, 0xC0, 0x8F, 0xE0, // add ip, pc, ip 0x04, 0xC0, 0x2D, 0xE5, // str ip, [sp, #-4]! // jump through dyld_stub_binder 0x08, 0xC0, 0x9F, 0xE5, // ldr ip, L2 0x0C, 0xC0, 0x8F, 0xE0, // add ip, pc, ip 0x00, 0xF0, 0x9C, 0xE5, // ldr pc, [ip] 0x00, 0x00, 0x00, 0x00, // L1: .long fFastStubGOTAtom - (helper+16) 0x00, 0x00, 0x00, 0x00 }, // L2: .long dyld_stub_binder - (helper+28) { Reference::KindArch::ARM, delta32, 28, 0xC }, { false, 0, 0, 0 }, { Reference::KindArch::ARM, delta32, 32, 0x04 }, { false, 0, 0, 0 } }; const ArchHandler::StubInfo &ArchHandler_arm::stubInfo() { // If multiple kinds of stubs are supported, select which StubInfo here. return _sStubInfoArmPIC; } bool ArchHandler_arm::isCallSite(const Reference &ref) { switch (ref.kindValue()) { case thumb_b22: case thumb_bl22: case arm_b24: case arm_bl24: return true; default: return false; } } bool ArchHandler_arm::isPointer(const Reference &ref) { return (ref.kindValue() == pointer32); } bool ArchHandler_arm::isNonCallBranch(const Reference &ref) { switch (ref.kindValue()) { case thumb_b22: case arm_b24: return true; default: return false; } } bool ArchHandler_arm::isPairedReloc(const Relocation &reloc) { switch (reloc.type) { case ARM_RELOC_SECTDIFF: case ARM_RELOC_LOCAL_SECTDIFF: case ARM_RELOC_HALF_SECTDIFF: case ARM_RELOC_HALF: return true; default: return false; } } /// Trace references from stub atom to lazy pointer to target and get its name. StringRef ArchHandler_arm::stubName(const DefinedAtom &stubAtom) { assert(stubAtom.contentType() == DefinedAtom::typeStub); for (const Reference *ref : stubAtom) { if (const DefinedAtom* lp = dyn_cast(ref->target())) { if (lp->contentType() != DefinedAtom::typeLazyPointer) continue; for (const Reference *ref2 : *lp) { if (ref2->kindValue() != lazyPointer) continue; return ref2->target()->name(); } } } return "stub"; } /// Extract displacement from an ARM b/bl/blx instruction. int32_t ArchHandler_arm::getDisplacementFromArmBranch(uint32_t instruction) { // Sign-extend imm24 int32_t displacement = (instruction & 0x00FFFFFF) << 2; if ((displacement & 0x02000000) != 0) displacement |= 0xFC000000; // If this is BLX and H bit set, add 2. if ((instruction & 0xFF000000) == 0xFB000000) displacement += 2; return displacement; } /// Update an ARM b/bl/blx instruction, switching bl <-> blx as needed. uint32_t ArchHandler_arm::setDisplacementInArmBranch(uint32_t instruction, int32_t displacement, bool targetIsThumb) { assert((displacement <= 33554428) && (displacement > (-33554432)) && "arm branch out of range"); bool is_blx = ((instruction & 0xF0000000) == 0xF0000000); uint32_t newInstruction = (instruction & 0xFF000000); uint32_t h = 0; if (targetIsThumb) { // Force use of BLX. newInstruction = 0xFA000000; if (!is_blx) { assert(((instruction & 0xF0000000) == 0xE0000000) && "no conditional arm blx"); assert(((instruction & 0xFF000000) == 0xEB000000) && "no arm pc-rel BX instruction"); } if (displacement & 2) h = 1; } else { // Force use of B/BL. if (is_blx) newInstruction = 0xEB000000; } newInstruction |= (h << 24) | ((displacement >> 2) & 0x00FFFFFF); return newInstruction; } /// Extract displacement from a thumb b/bl/blx instruction. int32_t ArchHandler_arm::getDisplacementFromThumbBranch(uint32_t instruction, uint32_t instrAddr) { bool is_blx = ((instruction & 0xD000F800) == 0xC000F000); uint32_t s = (instruction >> 10) & 0x1; uint32_t j1 = (instruction >> 29) & 0x1; uint32_t j2 = (instruction >> 27) & 0x1; uint32_t imm10 = instruction & 0x3FF; uint32_t imm11 = (instruction >> 16) & 0x7FF; uint32_t i1 = (j1 == s); uint32_t i2 = (j2 == s); uint32_t dis = (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1); int32_t sdis = dis; int32_t result = s ? (sdis | 0xFE000000) : sdis; if (is_blx && (instrAddr & 0x2)) { // The thumb blx instruction always has low bit of imm11 as zero. The way // a 2-byte aligned blx can branch to a 4-byte aligned ARM target is that // the blx instruction always 4-byte aligns the pc before adding the // displacement from the blx. We must emulate that when decoding this. result -= 2; } return result; } /// Update a thumb b/bl/blx instruction, switching bl <-> blx as needed. uint32_t ArchHandler_arm::setDisplacementInThumbBranch(uint32_t instruction, uint32_t instrAddr, int32_t displacement, bool targetIsThumb) { assert((displacement <= 16777214) && (displacement > (-16777216)) && "thumb branch out of range"); bool is_bl = ((instruction & 0xD000F800) == 0xD000F000); bool is_blx = ((instruction & 0xD000F800) == 0xC000F000); bool is_b = ((instruction & 0xD000F800) == 0x9000F000); uint32_t newInstruction = (instruction & 0xD000F800); if (is_bl || is_blx) { if (targetIsThumb) { newInstruction = 0xD000F000; // Use bl } else { newInstruction = 0xC000F000; // Use blx // See note in getDisplacementFromThumbBranch() about blx. if (instrAddr & 0x2) displacement += 2; } } else if (is_b) { assert(targetIsThumb && "no pc-rel thumb branch instruction that " "switches to arm mode"); } else { llvm_unreachable("thumb branch22 reloc on a non-branch instruction"); } uint32_t s = (uint32_t)(displacement >> 24) & 0x1; uint32_t i1 = (uint32_t)(displacement >> 23) & 0x1; uint32_t i2 = (uint32_t)(displacement >> 22) & 0x1; uint32_t imm10 = (uint32_t)(displacement >> 12) & 0x3FF; uint32_t imm11 = (uint32_t)(displacement >> 1) & 0x7FF; uint32_t j1 = (i1 == s); uint32_t j2 = (i2 == s); uint32_t nextDisp = (j1 << 13) | (j2 << 11) | imm11; uint32_t firstDisp = (s << 10) | imm10; newInstruction |= (nextDisp << 16) | firstDisp; return newInstruction; } bool ArchHandler_arm::isThumbMovw(uint32_t instruction) { return (instruction & 0x8000FBF0) == 0x0000F240; } bool ArchHandler_arm::isThumbMovt(uint32_t instruction) { return (instruction & 0x8000FBF0) == 0x0000F2C0; } bool ArchHandler_arm::isArmMovw(uint32_t instruction) { return (instruction & 0x0FF00000) == 0x03000000; } bool ArchHandler_arm::isArmMovt(uint32_t instruction) { return (instruction & 0x0FF00000) == 0x03400000; } uint16_t ArchHandler_arm::getWordFromThumbMov(uint32_t instruction) { assert(isThumbMovw(instruction) || isThumbMovt(instruction)); uint32_t i = ((instruction & 0x00000400) >> 10); uint32_t imm4 = (instruction & 0x0000000F); uint32_t imm3 = ((instruction & 0x70000000) >> 28); uint32_t imm8 = ((instruction & 0x00FF0000) >> 16); return (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8; } uint16_t ArchHandler_arm::getWordFromArmMov(uint32_t instruction) { assert(isArmMovw(instruction) || isArmMovt(instruction)); uint32_t imm4 = ((instruction & 0x000F0000) >> 16); uint32_t imm12 = (instruction & 0x00000FFF); return (imm4 << 12) | imm12; } uint32_t ArchHandler_arm::setWordFromThumbMov(uint32_t instr, uint16_t word) { assert(isThumbMovw(instr) || isThumbMovt(instr)); uint32_t imm4 = (word & 0xF000) >> 12; uint32_t i = (word & 0x0800) >> 11; uint32_t imm3 = (word & 0x0700) >> 8; uint32_t imm8 = word & 0x00FF; return (instr & 0x8F00FBF0) | imm4 | (i << 10) | (imm3 << 28) | (imm8 << 16); } uint32_t ArchHandler_arm::setWordFromArmMov(uint32_t instr, uint16_t word) { assert(isArmMovw(instr) || isArmMovt(instr)); uint32_t imm4 = (word & 0xF000) >> 12; uint32_t imm12 = word & 0x0FFF; return (instr & 0xFFF0F000) | (imm4 << 16) | imm12; } uint32_t ArchHandler_arm::clearThumbBit(uint32_t value, const Atom *target) { // The assembler often adds one to the address of a thumb function. // We need to undo that so it does not look like an addend. if (value & 1) { if (isa(target)) { const MachODefinedAtom *machoTarget = reinterpret_cast(target); if (machoTarget->isThumb()) value &= -2; // mask off thumb-bit } } return value; } llvm::Error ArchHandler_arm::getReferenceInfo( const Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool isBig, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) { const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom]; uint64_t targetAddress; uint32_t instruction = *(const ulittle32_t *)fixupContent; int32_t displacement; switch (relocPattern(reloc)) { case ARM_THUMB_RELOC_BR22 | rPcRel | rExtern | rLength4: // ex: bl _foo (and _foo is undefined) if ((instruction & 0xD000F800) == 0x9000F000) *kind = thumb_b22; else *kind = thumb_bl22; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; // Instruction contains branch to addend. displacement = getDisplacementFromThumbBranch(instruction, fixupAddress); *addend = fixupAddress + 4 + displacement; return llvm::Error::success(); case ARM_THUMB_RELOC_BR22 | rPcRel | rLength4: // ex: bl _foo (and _foo is defined) if ((instruction & 0xD000F800) == 0x9000F000) *kind = thumb_b22; else *kind = thumb_bl22; displacement = getDisplacementFromThumbBranch(instruction, fixupAddress); targetAddress = fixupAddress + 4 + displacement; return atomFromAddress(reloc.symbol, targetAddress, target, addend); case ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4: // ex: bl _foo+4 (and _foo is defined) if ((instruction & 0xD000F800) == 0x9000F000) *kind = thumb_b22; else *kind = thumb_bl22; displacement = getDisplacementFromThumbBranch(instruction, fixupAddress); targetAddress = fixupAddress + 4 + displacement; if (auto ec = atomFromAddress(0, reloc.value, target, addend)) return ec; // reloc.value is target atom's address. Instruction contains branch // to atom+addend. *addend += (targetAddress - reloc.value); return llvm::Error::success(); case ARM_RELOC_BR24 | rPcRel | rExtern | rLength4: // ex: bl _foo (and _foo is undefined) if (((instruction & 0x0F000000) == 0x0A000000) && ((instruction & 0xF0000000) != 0xF0000000)) *kind = arm_b24; else *kind = arm_bl24; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; // Instruction contains branch to addend. displacement = getDisplacementFromArmBranch(instruction); *addend = fixupAddress + 8 + displacement; return llvm::Error::success(); case ARM_RELOC_BR24 | rPcRel | rLength4: // ex: bl _foo (and _foo is defined) if (((instruction & 0x0F000000) == 0x0A000000) && ((instruction & 0xF0000000) != 0xF0000000)) *kind = arm_b24; else *kind = arm_bl24; displacement = getDisplacementFromArmBranch(instruction); targetAddress = fixupAddress + 8 + displacement; return atomFromAddress(reloc.symbol, targetAddress, target, addend); case ARM_RELOC_BR24 | rScattered | rPcRel | rLength4: // ex: bl _foo+4 (and _foo is defined) if (((instruction & 0x0F000000) == 0x0A000000) && ((instruction & 0xF0000000) != 0xF0000000)) *kind = arm_b24; else *kind = arm_bl24; displacement = getDisplacementFromArmBranch(instruction); targetAddress = fixupAddress + 8 + displacement; if (auto ec = atomFromAddress(0, reloc.value, target, addend)) return ec; // reloc.value is target atom's address. Instruction contains branch // to atom+addend. *addend += (targetAddress - reloc.value); return llvm::Error::success(); case ARM_RELOC_VANILLA | rExtern | rLength4: // ex: .long _foo (and _foo is undefined) *kind = pointer32; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = instruction; return llvm::Error::success(); case ARM_RELOC_VANILLA | rLength4: // ex: .long _foo (and _foo is defined) *kind = pointer32; if (auto ec = atomFromAddress(reloc.symbol, instruction, target, addend)) return ec; *addend = clearThumbBit((uint32_t) * addend, *target); return llvm::Error::success(); case ARM_RELOC_VANILLA | rScattered | rLength4: // ex: .long _foo+a (and _foo is defined) *kind = pointer32; if (auto ec = atomFromAddress(0, reloc.value, target, addend)) return ec; *addend += (clearThumbBit(instruction, *target) - reloc.value); return llvm::Error::success(); default: return llvm::make_error("unsupported arm relocation type"); } return llvm::Error::success(); } llvm::Error ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1, const normalized::Relocation &reloc2, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool isBig, bool scatterable, FindAtomBySectionAndAddress atomFromAddr, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) { bool pointerDiff = false; bool funcRel; bool top; bool thumbReloc; switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) { case ((ARM_RELOC_HALF_SECTDIFF | rScattered | rLenThmbLo) << 16 | ARM_RELOC_PAIR | rScattered | rLenThmbLo): // ex: movw r1, :lower16:(_x-L1) [thumb mode] *kind = thumb_movw_funcRel; funcRel = true; top = false; thumbReloc = true; break; case ((ARM_RELOC_HALF_SECTDIFF | rScattered | rLenThmbHi) << 16 | ARM_RELOC_PAIR | rScattered | rLenThmbHi): // ex: movt r1, :upper16:(_x-L1) [thumb mode] *kind = thumb_movt_funcRel; funcRel = true; top = true; thumbReloc = true; break; case ((ARM_RELOC_HALF_SECTDIFF | rScattered | rLenArmLo) << 16 | ARM_RELOC_PAIR | rScattered | rLenArmLo): // ex: movw r1, :lower16:(_x-L1) [arm mode] *kind = arm_movw_funcRel; funcRel = true; top = false; thumbReloc = false; break; case ((ARM_RELOC_HALF_SECTDIFF | rScattered | rLenArmHi) << 16 | ARM_RELOC_PAIR | rScattered | rLenArmHi): // ex: movt r1, :upper16:(_x-L1) [arm mode] *kind = arm_movt_funcRel; funcRel = true; top = true; thumbReloc = false; break; case ((ARM_RELOC_HALF | rLenThmbLo) << 16 | ARM_RELOC_PAIR | rLenThmbLo): // ex: movw r1, :lower16:_x [thumb mode] *kind = thumb_movw; funcRel = false; top = false; thumbReloc = true; break; case ((ARM_RELOC_HALF | rLenThmbHi) << 16 | ARM_RELOC_PAIR | rLenThmbHi): // ex: movt r1, :upper16:_x [thumb mode] *kind = thumb_movt; funcRel = false; top = true; thumbReloc = true; break; case ((ARM_RELOC_HALF | rLenArmLo) << 16 | ARM_RELOC_PAIR | rLenArmLo): // ex: movw r1, :lower16:_x [arm mode] *kind = arm_movw; funcRel = false; top = false; thumbReloc = false; break; case ((ARM_RELOC_HALF | rLenArmHi) << 16 | ARM_RELOC_PAIR | rLenArmHi): // ex: movt r1, :upper16:_x [arm mode] *kind = arm_movt; funcRel = false; top = true; thumbReloc = false; break; case ((ARM_RELOC_HALF | rScattered | rLenThmbLo) << 16 | ARM_RELOC_PAIR | rLenThmbLo): // ex: movw r1, :lower16:_x+a [thumb mode] *kind = thumb_movw; funcRel = false; top = false; thumbReloc = true; break; case ((ARM_RELOC_HALF | rScattered | rLenThmbHi) << 16 | ARM_RELOC_PAIR | rLenThmbHi): // ex: movt r1, :upper16:_x+a [thumb mode] *kind = thumb_movt; funcRel = false; top = true; thumbReloc = true; break; case ((ARM_RELOC_HALF | rScattered | rLenArmLo) << 16 | ARM_RELOC_PAIR | rLenArmLo): // ex: movw r1, :lower16:_x+a [arm mode] *kind = arm_movw; funcRel = false; top = false; thumbReloc = false; break; case ((ARM_RELOC_HALF | rScattered | rLenArmHi) << 16 | ARM_RELOC_PAIR | rLenArmHi): // ex: movt r1, :upper16:_x+a [arm mode] *kind = arm_movt; funcRel = false; top = true; thumbReloc = false; break; case ((ARM_RELOC_HALF | rExtern | rLenThmbLo) << 16 | ARM_RELOC_PAIR | rLenThmbLo): // ex: movw r1, :lower16:_undef [thumb mode] *kind = thumb_movw; funcRel = false; top = false; thumbReloc = true; break; case ((ARM_RELOC_HALF | rExtern | rLenThmbHi) << 16 | ARM_RELOC_PAIR | rLenThmbHi): // ex: movt r1, :upper16:_undef [thumb mode] *kind = thumb_movt; funcRel = false; top = true; thumbReloc = true; break; case ((ARM_RELOC_HALF | rExtern | rLenArmLo) << 16 | ARM_RELOC_PAIR | rLenArmLo): // ex: movw r1, :lower16:_undef [arm mode] *kind = arm_movw; funcRel = false; top = false; thumbReloc = false; break; case ((ARM_RELOC_HALF | rExtern | rLenArmHi) << 16 | ARM_RELOC_PAIR | rLenArmHi): // ex: movt r1, :upper16:_undef [arm mode] *kind = arm_movt; funcRel = false; top = true; thumbReloc = false; break; case ((ARM_RELOC_SECTDIFF | rScattered | rLength4) << 16 | ARM_RELOC_PAIR | rScattered | rLength4): case ((ARM_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 | ARM_RELOC_PAIR | rScattered | rLength4): // ex: .long _foo - . pointerDiff = true; break; default: return llvm::make_error("unsupported arm relocation pair"); } const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom]; uint32_t instruction = *(const ulittle32_t *)fixupContent; uint32_t value; uint32_t fromAddress; uint32_t toAddress; uint16_t instruction16; uint16_t other16; const lld::Atom *fromTarget; Reference::Addend offsetInTo; Reference::Addend offsetInFrom; if (pointerDiff) { toAddress = reloc1.value; fromAddress = reloc2.value; if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo)) return ec; if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom)) return ec; if (scatterable && (fromTarget != inAtom)) return llvm::make_error( "SECTDIFF relocation where subtrahend label is not in atom"); *kind = delta32; value = clearThumbBit(instruction, *target); *addend = (int32_t)(value - (toAddress - fixupAddress)); } else if (funcRel) { toAddress = reloc1.value; fromAddress = reloc2.value; if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo)) return ec; if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom)) return ec; if (fromTarget != inAtom) return llvm::make_error("ARM_RELOC_HALF_SECTDIFF relocation" " where subtrahend label is not in atom"); other16 = (reloc2.offset & 0xFFFF); if (thumbReloc) { if (top) { if (!isThumbMovt(instruction)) return llvm::make_error("expected movt instruction"); } else { if (!isThumbMovw(instruction)) return llvm::make_error("expected movw instruction"); } instruction16 = getWordFromThumbMov(instruction); } else { if (top) { if (!isArmMovt(instruction)) return llvm::make_error("expected movt instruction"); } else { if (!isArmMovw(instruction)) return llvm::make_error("expected movw instruction"); } instruction16 = getWordFromArmMov(instruction); } if (top) value = (instruction16 << 16) | other16; else value = (other16 << 16) | instruction16; value = clearThumbBit(value, *target); int64_t ta = (int64_t) value - (toAddress - fromAddress); *addend = ta - offsetInFrom; return llvm::Error::success(); } else { uint32_t sectIndex; if (thumbReloc) { if (top) { if (!isThumbMovt(instruction)) return llvm::make_error("expected movt instruction"); } else { if (!isThumbMovw(instruction)) return llvm::make_error("expected movw instruction"); } instruction16 = getWordFromThumbMov(instruction); } else { if (top) { if (!isArmMovt(instruction)) return llvm::make_error("expected movt instruction"); } else { if (!isArmMovw(instruction)) return llvm::make_error("expected movw instruction"); } instruction16 = getWordFromArmMov(instruction); } other16 = (reloc2.offset & 0xFFFF); if (top) value = (instruction16 << 16) | other16; else value = (other16 << 16) | instruction16; if (reloc1.isExtern) { if (auto ec = atomFromSymbolIndex(reloc1.symbol, target)) return ec; *addend = value; } else { if (reloc1.scattered) { toAddress = reloc1.value; sectIndex = 0; } else { toAddress = value; sectIndex = reloc1.symbol; } if (auto ec = atomFromAddr(sectIndex, toAddress, target, &offsetInTo)) return ec; *addend = value - toAddress; } } return llvm::Error::success(); } void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *loc, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress, bool &thumbMode, bool targetIsThumb) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return; assert(ref.kindArch() == Reference::KindArch::ARM); ulittle32_t *loc32 = reinterpret_cast(loc); int32_t displacement; uint16_t value16; uint32_t value32; switch (static_cast(ref.kindValue())) { case modeThumbCode: thumbMode = true; break; case modeArmCode: thumbMode = false; break; case modeData: break; case thumb_b22: case thumb_bl22: assert(thumbMode); displacement = (targetAddress - (fixupAddress + 4)) + ref.addend(); value32 = setDisplacementInThumbBranch(*loc32, fixupAddress, displacement, targetIsThumb); *loc32 = value32; break; case thumb_movw: assert(thumbMode); value16 = (targetAddress + ref.addend()) & 0xFFFF; if (targetIsThumb) value16 |= 1; *loc32 = setWordFromThumbMov(*loc32, value16); break; case thumb_movt: assert(thumbMode); value16 = (targetAddress + ref.addend()) >> 16; *loc32 = setWordFromThumbMov(*loc32, value16); break; case thumb_movw_funcRel: assert(thumbMode); value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF; if (targetIsThumb) value16 |= 1; *loc32 = setWordFromThumbMov(*loc32, value16); break; case thumb_movt_funcRel: assert(thumbMode); value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16; *loc32 = setWordFromThumbMov(*loc32, value16); break; case arm_b24: case arm_bl24: assert(!thumbMode); displacement = (targetAddress - (fixupAddress + 8)) + ref.addend(); value32 = setDisplacementInArmBranch(*loc32, displacement, targetIsThumb); *loc32 = value32; break; case arm_movw: assert(!thumbMode); value16 = (targetAddress + ref.addend()) & 0xFFFF; if (targetIsThumb) value16 |= 1; *loc32 = setWordFromArmMov(*loc32, value16); break; case arm_movt: assert(!thumbMode); value16 = (targetAddress + ref.addend()) >> 16; *loc32 = setWordFromArmMov(*loc32, value16); break; case arm_movw_funcRel: assert(!thumbMode); value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF; if (targetIsThumb) value16 |= 1; *loc32 = setWordFromArmMov(*loc32, value16); break; case arm_movt_funcRel: assert(!thumbMode); value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16; *loc32 = setWordFromArmMov(*loc32, value16); break; case pointer32: if (targetIsThumb) *loc32 = targetAddress + ref.addend() + 1; else *loc32 = targetAddress + ref.addend(); break; case delta32: if (targetIsThumb) *loc32 = targetAddress - fixupAddress + ref.addend() + 1; else *loc32 = targetAddress - fixupAddress + ref.addend(); break; case lazyPointer: // do nothing break; case lazyImmediateLocation: *loc32 = ref.addend(); break; case invalid: llvm_unreachable("invalid ARM Reference Kind"); break; } } void ArchHandler_arm::generateAtomContent(const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress, FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress, llvm::MutableArrayRef atomContentBuffer) { // Copy raw bytes. std::copy(atom.rawContent().begin(), atom.rawContent().end(), atomContentBuffer.begin()); // Apply fix-ups. bool thumbMode = false; for (const Reference *ref : atom) { uint32_t offset = ref->offsetInAtom(); const Atom *target = ref->target(); uint64_t targetAddress = 0; bool targetIsThumb = false; if (const DefinedAtom *defTarg = dyn_cast(target)) { targetAddress = findAddress(*target); targetIsThumb = isThumbFunction(*defTarg); } uint64_t atomAddress = findAddress(atom); uint64_t fixupAddress = atomAddress + offset; if (relocatable) { applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress, targetAddress, atomAddress, thumbMode, targetIsThumb); } else { applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress, targetAddress, atomAddress, thumbMode, targetIsThumb); } } } bool ArchHandler_arm::useExternalRelocationTo(const Atom &target) { // Undefined symbols are referenced via external relocations. if (isa(&target)) return true; if (const DefinedAtom *defAtom = dyn_cast(&target)) { switch (defAtom->merge()) { case DefinedAtom::mergeAsTentative: // Tentative definitions are referenced via external relocations. return true; case DefinedAtom::mergeAsWeak: case DefinedAtom::mergeAsWeakAndAddressUsed: // Global weak-defs are referenced via external relocations. return (defAtom->scope() == DefinedAtom::scopeGlobal); default: break; } } // Everything else is reference via an internal relocation. return false; } void ArchHandler_arm::applyFixupRelocatable(const Reference &ref, uint8_t *loc, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress, bool &thumbMode, bool targetIsThumb) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return; assert(ref.kindArch() == Reference::KindArch::ARM); bool useExternalReloc = useExternalRelocationTo(*ref.target()); ulittle32_t *loc32 = reinterpret_cast(loc); int32_t displacement; uint16_t value16; uint32_t value32; bool targetIsUndef = isa(ref.target()); switch (static_cast(ref.kindValue())) { case modeThumbCode: thumbMode = true; break; case modeArmCode: thumbMode = false; break; case modeData: break; case thumb_b22: case thumb_bl22: assert(thumbMode); if (useExternalReloc) displacement = (ref.addend() - (fixupAddress + 4)); else displacement = (targetAddress - (fixupAddress + 4)) + ref.addend(); value32 = setDisplacementInThumbBranch(*loc32, fixupAddress, displacement, targetIsUndef || targetIsThumb); *loc32 = value32; break; case thumb_movw: assert(thumbMode); if (useExternalReloc) value16 = ref.addend() & 0xFFFF; else value16 = (targetAddress + ref.addend()) & 0xFFFF; *loc32 = setWordFromThumbMov(*loc32, value16); break; case thumb_movt: assert(thumbMode); if (useExternalReloc) value16 = ref.addend() >> 16; else value16 = (targetAddress + ref.addend()) >> 16; *loc32 = setWordFromThumbMov(*loc32, value16); break; case thumb_movw_funcRel: assert(thumbMode); value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF; *loc32 = setWordFromThumbMov(*loc32, value16); break; case thumb_movt_funcRel: assert(thumbMode); value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16; *loc32 = setWordFromThumbMov(*loc32, value16); break; case arm_b24: case arm_bl24: assert(!thumbMode); if (useExternalReloc) displacement = (ref.addend() - (fixupAddress + 8)); else displacement = (targetAddress - (fixupAddress + 8)) + ref.addend(); value32 = setDisplacementInArmBranch(*loc32, displacement, targetIsThumb); *loc32 = value32; break; case arm_movw: assert(!thumbMode); if (useExternalReloc) value16 = ref.addend() & 0xFFFF; else value16 = (targetAddress + ref.addend()) & 0xFFFF; *loc32 = setWordFromArmMov(*loc32, value16); break; case arm_movt: assert(!thumbMode); if (useExternalReloc) value16 = ref.addend() >> 16; else value16 = (targetAddress + ref.addend()) >> 16; *loc32 = setWordFromArmMov(*loc32, value16); break; case arm_movw_funcRel: assert(!thumbMode); value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF; *loc32 = setWordFromArmMov(*loc32, value16); break; case arm_movt_funcRel: assert(!thumbMode); value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16; *loc32 = setWordFromArmMov(*loc32, value16); break; case pointer32: *loc32 = targetAddress + ref.addend(); break; case delta32: *loc32 = targetAddress - fixupAddress + ref.addend(); break; case lazyPointer: case lazyImmediateLocation: // do nothing break; case invalid: llvm_unreachable("invalid ARM Reference Kind"); break; } } void ArchHandler_arm::appendSectionRelocations( const DefinedAtom &atom, uint64_t atomSectionOffset, const Reference &ref, FindSymbolIndexForAtom symbolIndexForAtom, FindSectionIndexForAtom sectionIndexForAtom, FindAddressForAtom addressForAtom, normalized::Relocations &relocs) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return; assert(ref.kindArch() == Reference::KindArch::ARM); uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom(); bool useExternalReloc = useExternalRelocationTo(*ref.target()); uint32_t targetAtomAddress; uint32_t fromAtomAddress; uint16_t other16; switch (static_cast(ref.kindValue())) { case modeThumbCode: case modeArmCode: case modeData: // Do nothing. break; case thumb_b22: case thumb_bl22: if (useExternalReloc) { appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM_THUMB_RELOC_BR22 | rExtern | rPcRel | rLength4); } else { if (ref.addend() != 0) appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4); else appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0, ARM_THUMB_RELOC_BR22 | rPcRel | rLength4); } break; case thumb_movw: if (useExternalReloc) { other16 = ref.addend() >> 16; appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM_RELOC_HALF | rExtern | rLenThmbLo); appendReloc(relocs, other16, 0, 0, ARM_RELOC_PAIR | rLenThmbLo); } else { targetAtomAddress = addressForAtom(*ref.target()); if (ref.addend() != 0) { other16 = (targetAtomAddress + ref.addend()) >> 16; appendReloc(relocs, sectionOffset, 0, targetAtomAddress, ARM_RELOC_HALF | rScattered | rLenThmbLo); appendReloc(relocs, other16, 0, 0, ARM_RELOC_PAIR | rLenThmbLo); } else { other16 = (targetAtomAddress + ref.addend()) >> 16; appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0, ARM_RELOC_HALF | rLenThmbLo); appendReloc(relocs, other16, 0, 0, ARM_RELOC_PAIR | rLenThmbLo); } } break; case thumb_movt: if (useExternalReloc) { other16 = ref.addend() & 0xFFFF; appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM_RELOC_HALF | rExtern | rLenThmbHi); appendReloc(relocs, other16, 0, 0, ARM_RELOC_PAIR | rLenThmbHi); } else { targetAtomAddress = addressForAtom(*ref.target()); if (ref.addend() != 0) { other16 = (targetAtomAddress + ref.addend()) & 0xFFFF; appendReloc(relocs, sectionOffset, 0, targetAtomAddress, ARM_RELOC_HALF | rScattered | rLenThmbHi); appendReloc(relocs, other16, 0, 0, ARM_RELOC_PAIR | rLenThmbHi); } else { other16 = (targetAtomAddress + ref.addend()) & 0xFFFF; appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0, ARM_RELOC_HALF | rLenThmbHi); appendReloc(relocs, other16, 0, 0, ARM_RELOC_PAIR | rLenThmbHi); } } break; case thumb_movw_funcRel: fromAtomAddress = addressForAtom(atom); targetAtomAddress = addressForAtom(*ref.target()); other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) >> 16; appendReloc(relocs, sectionOffset, 0, targetAtomAddress, ARM_RELOC_HALF_SECTDIFF | rScattered | rLenThmbLo); appendReloc(relocs, other16, 0, fromAtomAddress, ARM_RELOC_PAIR | rScattered | rLenThmbLo); break; case thumb_movt_funcRel: fromAtomAddress = addressForAtom(atom); targetAtomAddress = addressForAtom(*ref.target()); other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) & 0xFFFF; appendReloc(relocs, sectionOffset, 0, targetAtomAddress, ARM_RELOC_HALF_SECTDIFF | rScattered | rLenThmbHi); appendReloc(relocs, other16, 0, fromAtomAddress, ARM_RELOC_PAIR | rScattered | rLenThmbHi); break; case arm_b24: case arm_bl24: if (useExternalReloc) { appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM_RELOC_BR24 | rExtern | rPcRel | rLength4); } else { if (ref.addend() != 0) appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), ARM_RELOC_BR24 | rScattered | rPcRel | rLength4); else appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0, ARM_RELOC_BR24 | rPcRel | rLength4); } break; case arm_movw: if (useExternalReloc) { other16 = ref.addend() >> 16; appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM_RELOC_HALF | rExtern | rLenArmLo); appendReloc(relocs, other16, 0, 0, ARM_RELOC_PAIR | rLenArmLo); } else { targetAtomAddress = addressForAtom(*ref.target()); if (ref.addend() != 0) { other16 = (targetAtomAddress + ref.addend()) >> 16; appendReloc(relocs, sectionOffset, 0, targetAtomAddress, ARM_RELOC_HALF | rScattered | rLenArmLo); appendReloc(relocs, other16, 0, 0, ARM_RELOC_PAIR | rLenArmLo); } else { other16 = (targetAtomAddress + ref.addend()) >> 16; appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0, ARM_RELOC_HALF | rLenArmLo); appendReloc(relocs, other16, 0, 0, ARM_RELOC_PAIR | rLenArmLo); } } break; case arm_movt: if (useExternalReloc) { other16 = ref.addend() & 0xFFFF; appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM_RELOC_HALF | rExtern | rLenArmHi); appendReloc(relocs, other16, 0, 0, ARM_RELOC_PAIR | rLenArmHi); } else { targetAtomAddress = addressForAtom(*ref.target()); if (ref.addend() != 0) { other16 = (targetAtomAddress + ref.addend()) & 0xFFFF; appendReloc(relocs, sectionOffset, 0, targetAtomAddress, ARM_RELOC_HALF | rScattered | rLenArmHi); appendReloc(relocs, other16, 0, 0, ARM_RELOC_PAIR | rLenArmHi); } else { other16 = (targetAtomAddress + ref.addend()) & 0xFFFF; appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0, ARM_RELOC_HALF | rLenArmHi); appendReloc(relocs, other16, 0, 0, ARM_RELOC_PAIR | rLenArmHi); } } break; case arm_movw_funcRel: fromAtomAddress = addressForAtom(atom); targetAtomAddress = addressForAtom(*ref.target()); other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) >> 16; appendReloc(relocs, sectionOffset, 0, targetAtomAddress, ARM_RELOC_HALF_SECTDIFF | rScattered | rLenArmLo); appendReloc(relocs, other16, 0, fromAtomAddress, ARM_RELOC_PAIR | rScattered | rLenArmLo); break; case arm_movt_funcRel: fromAtomAddress = addressForAtom(atom); targetAtomAddress = addressForAtom(*ref.target()); other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) & 0xFFFF; appendReloc(relocs, sectionOffset, 0, targetAtomAddress, ARM_RELOC_HALF_SECTDIFF | rScattered | rLenArmHi); appendReloc(relocs, other16, 0, fromAtomAddress, ARM_RELOC_PAIR | rScattered | rLenArmHi); break; case pointer32: if (useExternalReloc) { appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM_RELOC_VANILLA | rExtern | rLength4); } else { if (ref.addend() != 0) appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), ARM_RELOC_VANILLA | rScattered | rLength4); else appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0, ARM_RELOC_VANILLA | rLength4); } break; case delta32: appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), ARM_RELOC_SECTDIFF | rScattered | rLength4); appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) + ref.offsetInAtom(), ARM_RELOC_PAIR | rScattered | rLength4); break; case lazyPointer: case lazyImmediateLocation: // do nothing break; case invalid: llvm_unreachable("invalid ARM Reference Kind"); break; } } void ArchHandler_arm::addAdditionalReferences(MachODefinedAtom &atom) { if (atom.isThumb()) { atom.addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM, modeThumbCode, 0, &atom, 0); } } bool ArchHandler_arm::isThumbFunction(const DefinedAtom &atom) { for (const Reference *ref : atom) { if (ref->offsetInAtom() != 0) return false; if (ref->kindNamespace() != Reference::KindNamespace::mach_o) continue; assert(ref->kindArch() == Reference::KindArch::ARM); if (ref->kindValue() == modeThumbCode) return true; } return false; } class Thumb2ToArmShimAtom : public SimpleDefinedAtom { public: Thumb2ToArmShimAtom(MachOFile &file, StringRef targetName, const DefinedAtom &target) : SimpleDefinedAtom(file) { addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM, ArchHandler_arm::modeThumbCode, 0, this, 0); addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM, ArchHandler_arm::delta32, 8, &target, 0); std::string name = std::string(targetName) + "$shim"; StringRef tmp(name); _name = tmp.copy(file.allocator()); } ~Thumb2ToArmShimAtom() override = default; StringRef name() const override { return _name; } ContentType contentType() const override { return DefinedAtom::typeCode; } Alignment alignment() const override { return 4; } uint64_t size() const override { return 12; } ContentPermissions permissions() const override { return DefinedAtom::permR_X; } ArrayRef rawContent() const override { static const uint8_t bytes[] = { 0xDF, 0xF8, 0x04, 0xC0, // ldr ip, pc + 4 0xFF, 0x44, // add ip, pc, ip 0x60, 0x47, // ldr pc, [ip] 0x00, 0x00, 0x00, 0x00 }; // .long target - this assert(sizeof(bytes) == size()); return llvm::makeArrayRef(bytes, sizeof(bytes)); } private: StringRef _name; }; class ArmToThumbShimAtom : public SimpleDefinedAtom { public: ArmToThumbShimAtom(MachOFile &file, StringRef targetName, const DefinedAtom &target) : SimpleDefinedAtom(file) { addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM, ArchHandler_arm::delta32, 12, &target, 0); std::string name = std::string(targetName) + "$shim"; StringRef tmp(name); _name = tmp.copy(file.allocator()); } ~ArmToThumbShimAtom() override = default; StringRef name() const override { return _name; } ContentType contentType() const override { return DefinedAtom::typeCode; } Alignment alignment() const override { return 4; } uint64_t size() const override { return 16; } ContentPermissions permissions() const override { return DefinedAtom::permR_X; } ArrayRef rawContent() const override { static const uint8_t bytes[] = { 0x04, 0xC0, 0x9F, 0xE5, // ldr ip, pc + 4 0x0C, 0xC0, 0x8F, 0xE0, // add ip, pc, ip 0x1C, 0xFF, 0x2F, 0xE1, // ldr pc, [ip] 0x00, 0x00, 0x00, 0x00 }; // .long target - this assert(sizeof(bytes) == size()); return llvm::makeArrayRef(bytes, sizeof(bytes)); } private: StringRef _name; }; const DefinedAtom *ArchHandler_arm::createShim(MachOFile &file, bool thumbToArm, const DefinedAtom &target) { bool isStub = (target.contentType() == DefinedAtom::typeStub); StringRef targetName = isStub ? stubName(target) : target.name(); if (thumbToArm) return new (file.allocator()) Thumb2ToArmShimAtom(file, targetName, target); else return new (file.allocator()) ArmToThumbShimAtom(file, targetName, target); } std::unique_ptr ArchHandler::create_arm() { return std::unique_ptr(new ArchHandler_arm()); } } // namespace mach_o } // namespace lld Index: head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp =================================================================== --- head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp (revision 326908) +++ head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp (revision 326909) @@ -1,894 +1,898 @@ //===- lib/FileFormat/MachO/ArchHandler_arm64.cpp -------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "ArchHandler.h" #include "Atoms.h" #include "MachONormalizedFileBinaryUtils.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" using namespace llvm::MachO; using namespace lld::mach_o::normalized; namespace lld { namespace mach_o { using llvm::support::ulittle32_t; using llvm::support::ulittle64_t; using llvm::support::little32_t; using llvm::support::little64_t; class ArchHandler_arm64 : public ArchHandler { public: ArchHandler_arm64() = default; ~ArchHandler_arm64() override = default; const Registry::KindStrings *kindStrings() override { return _sKindStrings; } Reference::KindArch kindArch() override { return Reference::KindArch::AArch64; } /// Used by GOTPass to locate GOT References bool isGOTAccess(const Reference &ref, bool &canBypassGOT) override { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return false; assert(ref.kindArch() == Reference::KindArch::AArch64); switch (ref.kindValue()) { case gotPage21: case gotOffset12: canBypassGOT = true; return true; case delta32ToGOT: case unwindCIEToPersonalityFunction: case imageOffsetGot: canBypassGOT = false; return true; default: return false; } } /// Used by GOTPass to update GOT References. void updateReferenceToGOT(const Reference *ref, bool targetNowGOT) override { // If GOT slot was instanciated, transform: // gotPage21/gotOffset12 -> page21/offset12scale8 // If GOT slot optimized away, transform: // gotPage21/gotOffset12 -> page21/addOffset12 assert(ref->kindNamespace() == Reference::KindNamespace::mach_o); assert(ref->kindArch() == Reference::KindArch::AArch64); switch (ref->kindValue()) { case gotPage21: const_cast(ref)->setKindValue(page21); break; case gotOffset12: const_cast(ref)->setKindValue(targetNowGOT ? offset12scale8 : addOffset12); break; case delta32ToGOT: const_cast(ref)->setKindValue(delta32); break; case imageOffsetGot: const_cast(ref)->setKindValue(imageOffset); break; default: llvm_unreachable("Not a GOT reference"); } } const StubInfo &stubInfo() override { return _sStubInfo; } bool isCallSite(const Reference &) override; bool isNonCallBranch(const Reference &) override { return false; } bool isPointer(const Reference &) override; bool isPairedReloc(const normalized::Relocation &) override; bool needsCompactUnwind() override { return true; } Reference::KindValue imageOffsetKind() override { return imageOffset; } Reference::KindValue imageOffsetKindIndirect() override { return imageOffsetGot; } Reference::KindValue unwindRefToPersonalityFunctionKind() override { return unwindCIEToPersonalityFunction; } Reference::KindValue unwindRefToCIEKind() override { return negDelta32; } Reference::KindValue unwindRefToFunctionKind() override { return unwindFDEToFunction; } Reference::KindValue unwindRefToEhFrameKind() override { return unwindInfoToEhFrame; } Reference::KindValue pointerKind() override { return pointer64; } + Reference::KindValue lazyImmediateLocationKind() override { + return lazyImmediateLocation; + } + uint32_t dwarfCompactUnwindType() override { return 0x03000000; } llvm::Error getReferenceInfo(const normalized::Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool isBig, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) override; llvm::Error getPairReferenceInfo(const normalized::Relocation &reloc1, const normalized::Relocation &reloc2, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool isBig, bool scatterable, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) override; bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) override { return (atom->contentType() == DefinedAtom::typeCString); } void generateAtomContent(const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress, FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress, llvm::MutableArrayRef atomContentBuffer) override; void appendSectionRelocations(const DefinedAtom &atom, uint64_t atomSectionOffset, const Reference &ref, FindSymbolIndexForAtom symbolIndexForAtom, FindSectionIndexForAtom sectionIndexForAtom, FindAddressForAtom addressForAtom, normalized::Relocations &relocs) override; private: static const Registry::KindStrings _sKindStrings[]; static const StubInfo _sStubInfo; enum Arm64Kind : Reference::KindValue { invalid, /// for error condition // Kinds found in mach-o .o files: branch26, /// ex: bl _foo page21, /// ex: adrp x1, _foo@PAGE offset12, /// ex: ldrb w0, [x1, _foo@PAGEOFF] offset12scale2, /// ex: ldrs w0, [x1, _foo@PAGEOFF] offset12scale4, /// ex: ldr w0, [x1, _foo@PAGEOFF] offset12scale8, /// ex: ldr x0, [x1, _foo@PAGEOFF] offset12scale16, /// ex: ldr q0, [x1, _foo@PAGEOFF] gotPage21, /// ex: adrp x1, _foo@GOTPAGE gotOffset12, /// ex: ldr w0, [x1, _foo@GOTPAGEOFF] tlvPage21, /// ex: adrp x1, _foo@TLVPAGE tlvOffset12, /// ex: ldr w0, [x1, _foo@TLVPAGEOFF] pointer64, /// ex: .quad _foo delta64, /// ex: .quad _foo - . delta32, /// ex: .long _foo - . negDelta32, /// ex: .long . - _foo pointer64ToGOT, /// ex: .quad _foo@GOT delta32ToGOT, /// ex: .long _foo@GOT - . // Kinds introduced by Passes: addOffset12, /// Location contains LDR to change into ADD. lazyPointer, /// Location contains a lazy pointer. lazyImmediateLocation, /// Location contains immediate value used in stub. imageOffset, /// Location contains offset of atom in final image imageOffsetGot, /// Location contains offset of GOT entry for atom in /// final image (typically personality function). unwindCIEToPersonalityFunction, /// Nearly delta32ToGOT, but cannot be /// rematerialized in relocatable object /// (yay for implicit contracts!). unwindFDEToFunction, /// Nearly delta64, but cannot be rematerialized in /// relocatable object (yay for implicit contracts!). unwindInfoToEhFrame, /// Fix low 24 bits of compact unwind encoding to /// refer to __eh_frame entry. }; void applyFixupFinal(const Reference &ref, uint8_t *location, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress, uint64_t imageBaseAddress, FindAddressForAtom findSectionAddress); void applyFixupRelocatable(const Reference &ref, uint8_t *location, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress, bool targetUnnamed); // Utility functions for inspecting/updating instructions. static uint32_t setDisplacementInBranch26(uint32_t instr, int32_t disp); static uint32_t setDisplacementInADRP(uint32_t instr, int64_t disp); static Arm64Kind offset12KindFromInstruction(uint32_t instr); static uint32_t setImm12(uint32_t instr, uint32_t offset); }; const Registry::KindStrings ArchHandler_arm64::_sKindStrings[] = { LLD_KIND_STRING_ENTRY(invalid), LLD_KIND_STRING_ENTRY(branch26), LLD_KIND_STRING_ENTRY(page21), LLD_KIND_STRING_ENTRY(offset12), LLD_KIND_STRING_ENTRY(offset12scale2), LLD_KIND_STRING_ENTRY(offset12scale4), LLD_KIND_STRING_ENTRY(offset12scale8), LLD_KIND_STRING_ENTRY(offset12scale16), LLD_KIND_STRING_ENTRY(gotPage21), LLD_KIND_STRING_ENTRY(gotOffset12), LLD_KIND_STRING_ENTRY(tlvPage21), LLD_KIND_STRING_ENTRY(tlvOffset12), LLD_KIND_STRING_ENTRY(pointer64), LLD_KIND_STRING_ENTRY(delta64), LLD_KIND_STRING_ENTRY(delta32), LLD_KIND_STRING_ENTRY(negDelta32), LLD_KIND_STRING_ENTRY(pointer64ToGOT), LLD_KIND_STRING_ENTRY(delta32ToGOT), LLD_KIND_STRING_ENTRY(addOffset12), LLD_KIND_STRING_ENTRY(lazyPointer), LLD_KIND_STRING_ENTRY(lazyImmediateLocation), LLD_KIND_STRING_ENTRY(imageOffset), LLD_KIND_STRING_ENTRY(imageOffsetGot), LLD_KIND_STRING_ENTRY(unwindCIEToPersonalityFunction), LLD_KIND_STRING_ENTRY(unwindFDEToFunction), LLD_KIND_STRING_ENTRY(unwindInfoToEhFrame), LLD_KIND_STRING_END }; const ArchHandler::StubInfo ArchHandler_arm64::_sStubInfo = { "dyld_stub_binder", // Lazy pointer references { Reference::KindArch::AArch64, pointer64, 0, 0 }, { Reference::KindArch::AArch64, lazyPointer, 0, 0 }, // GOT pointer to dyld_stub_binder { Reference::KindArch::AArch64, pointer64, 0, 0 }, // arm64 code alignment 2^1 1, // Stub size and code 12, { 0x10, 0x00, 0x00, 0x90, // ADRP X16, lazy_pointer@page 0x10, 0x02, 0x40, 0xF9, // LDR X16, [X16, lazy_pointer@pageoff] 0x00, 0x02, 0x1F, 0xD6 }, // BR X16 { Reference::KindArch::AArch64, page21, 0, 0 }, { true, offset12scale8, 4, 0 }, // Stub Helper size and code 12, { 0x50, 0x00, 0x00, 0x18, // LDR W16, L0 0x00, 0x00, 0x00, 0x14, // LDR B helperhelper 0x00, 0x00, 0x00, 0x00 }, // L0: .long 0 { Reference::KindArch::AArch64, lazyImmediateLocation, 8, 0 }, { Reference::KindArch::AArch64, branch26, 4, 0 }, // Stub helper image cache content type DefinedAtom::typeGOT, // Stub Helper-Common size and code 24, // Stub helper alignment 2, { 0x11, 0x00, 0x00, 0x90, // ADRP X17, dyld_ImageLoaderCache@page 0x31, 0x02, 0x00, 0x91, // ADD X17, X17, dyld_ImageLoaderCache@pageoff 0xF0, 0x47, 0xBF, 0xA9, // STP X16/X17, [SP, #-16]! 0x10, 0x00, 0x00, 0x90, // ADRP X16, _fast_lazy_bind@page 0x10, 0x02, 0x40, 0xF9, // LDR X16, [X16,_fast_lazy_bind@pageoff] 0x00, 0x02, 0x1F, 0xD6 }, // BR X16 { Reference::KindArch::AArch64, page21, 0, 0 }, { true, offset12, 4, 0 }, { Reference::KindArch::AArch64, page21, 12, 0 }, { true, offset12scale8, 16, 0 } }; bool ArchHandler_arm64::isCallSite(const Reference &ref) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return false; assert(ref.kindArch() == Reference::KindArch::AArch64); return (ref.kindValue() == branch26); } bool ArchHandler_arm64::isPointer(const Reference &ref) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return false; assert(ref.kindArch() == Reference::KindArch::AArch64); Reference::KindValue kind = ref.kindValue(); return (kind == pointer64); } bool ArchHandler_arm64::isPairedReloc(const Relocation &r) { return ((r.type == ARM64_RELOC_ADDEND) || (r.type == ARM64_RELOC_SUBTRACTOR)); } uint32_t ArchHandler_arm64::setDisplacementInBranch26(uint32_t instr, int32_t displacement) { assert((displacement <= 134217727) && (displacement > (-134217728)) && "arm64 branch out of range"); return (instr & 0xFC000000) | ((uint32_t)(displacement >> 2) & 0x03FFFFFF); } uint32_t ArchHandler_arm64::setDisplacementInADRP(uint32_t instruction, int64_t displacement) { assert((displacement <= 0x100000000LL) && (displacement > (-0x100000000LL)) && "arm64 ADRP out of range"); assert(((instruction & 0x9F000000) == 0x90000000) && "reloc not on ADRP instruction"); uint32_t immhi = (displacement >> 9) & (0x00FFFFE0); uint32_t immlo = (displacement << 17) & (0x60000000); return (instruction & 0x9F00001F) | immlo | immhi; } ArchHandler_arm64::Arm64Kind ArchHandler_arm64::offset12KindFromInstruction(uint32_t instruction) { if (instruction & 0x08000000) { switch ((instruction >> 30) & 0x3) { case 0: if ((instruction & 0x04800000) == 0x04800000) return offset12scale16; return offset12; case 1: return offset12scale2; case 2: return offset12scale4; case 3: return offset12scale8; } } return offset12; } uint32_t ArchHandler_arm64::setImm12(uint32_t instruction, uint32_t offset) { assert(((offset & 0xFFFFF000) == 0) && "imm12 offset out of range"); uint32_t imm12 = offset << 10; return (instruction & 0xFFC003FF) | imm12; } llvm::Error ArchHandler_arm64::getReferenceInfo( const Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool isBig, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) { const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom]; switch (relocPattern(reloc)) { case ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4: // ex: bl _foo *kind = branch26; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = 0; return llvm::Error::success(); case ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4: // ex: adrp x1, _foo@PAGE *kind = page21; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = 0; return llvm::Error::success(); case ARM64_RELOC_PAGEOFF12 | rExtern | rLength4: // ex: ldr x0, [x1, _foo@PAGEOFF] *kind = offset12KindFromInstruction(*(const little32_t *)fixupContent); if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = 0; return llvm::Error::success(); case ARM64_RELOC_GOT_LOAD_PAGE21 | rPcRel | rExtern | rLength4: // ex: adrp x1, _foo@GOTPAGE *kind = gotPage21; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = 0; return llvm::Error::success(); case ARM64_RELOC_GOT_LOAD_PAGEOFF12 | rExtern | rLength4: // ex: ldr x0, [x1, _foo@GOTPAGEOFF] *kind = gotOffset12; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = 0; return llvm::Error::success(); case ARM64_RELOC_TLVP_LOAD_PAGE21 | rPcRel | rExtern | rLength4: // ex: adrp x1, _foo@TLVPAGE *kind = tlvPage21; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = 0; return llvm::Error::success(); case ARM64_RELOC_TLVP_LOAD_PAGEOFF12 | rExtern | rLength4: // ex: ldr x0, [x1, _foo@TLVPAGEOFF] *kind = tlvOffset12; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = 0; return llvm::Error::success(); case ARM64_RELOC_UNSIGNED | rExtern | rLength8: // ex: .quad _foo + N *kind = pointer64; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = *(const little64_t *)fixupContent; return llvm::Error::success(); case ARM64_RELOC_UNSIGNED | rLength8: // ex: .quad Lfoo + N *kind = pointer64; return atomFromAddress(reloc.symbol, *(const little64_t *)fixupContent, target, addend); case ARM64_RELOC_POINTER_TO_GOT | rExtern | rLength8: // ex: .quad _foo@GOT *kind = pointer64ToGOT; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = 0; return llvm::Error::success(); case ARM64_RELOC_POINTER_TO_GOT | rPcRel | rExtern | rLength4: // ex: .long _foo@GOT - . // If we are in an .eh_frame section, then the kind of the relocation should // not be delta32ToGOT. It may instead be unwindCIEToPersonalityFunction. if (inAtom->contentType() == DefinedAtom::typeCFI) *kind = unwindCIEToPersonalityFunction; else *kind = delta32ToGOT; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = 0; return llvm::Error::success(); default: return llvm::make_error("unsupported arm64 relocation type"); } } llvm::Error ArchHandler_arm64::getPairReferenceInfo( const normalized::Relocation &reloc1, const normalized::Relocation &reloc2, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool swap, bool scatterable, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) { const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom]; switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) { case ((ARM64_RELOC_ADDEND | rLength4) << 16 | ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4): // ex: bl _foo+8 *kind = branch26; if (auto ec = atomFromSymbolIndex(reloc2.symbol, target)) return ec; *addend = reloc1.symbol; return llvm::Error::success(); case ((ARM64_RELOC_ADDEND | rLength4) << 16 | ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4): // ex: adrp x1, _foo@PAGE *kind = page21; if (auto ec = atomFromSymbolIndex(reloc2.symbol, target)) return ec; *addend = reloc1.symbol; return llvm::Error::success(); case ((ARM64_RELOC_ADDEND | rLength4) << 16 | ARM64_RELOC_PAGEOFF12 | rExtern | rLength4): { // ex: ldr w0, [x1, _foo@PAGEOFF] uint32_t cont32 = (int32_t)*(const little32_t *)fixupContent; *kind = offset12KindFromInstruction(cont32); if (auto ec = atomFromSymbolIndex(reloc2.symbol, target)) return ec; *addend = reloc1.symbol; return llvm::Error::success(); } case ((ARM64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 | ARM64_RELOC_UNSIGNED | rExtern | rLength8): // ex: .quad _foo - . if (auto ec = atomFromSymbolIndex(reloc2.symbol, target)) return ec; // If we are in an .eh_frame section, then the kind of the relocation should // not be delta64. It may instead be unwindFDEToFunction. if (inAtom->contentType() == DefinedAtom::typeCFI) *kind = unwindFDEToFunction; else *kind = delta64; // The offsets of the 2 relocations must match if (reloc1.offset != reloc2.offset) return llvm::make_error( "paired relocs must have the same offset"); *addend = (int64_t)*(const little64_t *)fixupContent + offsetInAtom; return llvm::Error::success(); case ((ARM64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 | ARM64_RELOC_UNSIGNED | rExtern | rLength4): // ex: .quad _foo - . *kind = delta32; if (auto ec = atomFromSymbolIndex(reloc2.symbol, target)) return ec; *addend = (int32_t)*(const little32_t *)fixupContent + offsetInAtom; return llvm::Error::success(); default: return llvm::make_error("unsupported arm64 relocation pair"); } } void ArchHandler_arm64::generateAtomContent( const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress, FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress, llvm::MutableArrayRef atomContentBuffer) { // Copy raw bytes. std::copy(atom.rawContent().begin(), atom.rawContent().end(), atomContentBuffer.begin()); // Apply fix-ups. #ifndef NDEBUG if (atom.begin() != atom.end()) { DEBUG_WITH_TYPE("atom-content", llvm::dbgs() << "Applying fixups to atom:\n" << " address=" << llvm::format(" 0x%09lX", &atom) << ", file=#" << atom.file().ordinal() << ", atom=#" << atom.ordinal() << ", name=" << atom.name() << ", type=" << atom.contentType() << "\n"); } #endif for (const Reference *ref : atom) { uint32_t offset = ref->offsetInAtom(); const Atom *target = ref->target(); bool targetUnnamed = target->name().empty(); uint64_t targetAddress = 0; if (isa(target)) targetAddress = findAddress(*target); uint64_t atomAddress = findAddress(atom); uint64_t fixupAddress = atomAddress + offset; if (relocatable) { applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress, targetAddress, atomAddress, targetUnnamed); } else { applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress, targetAddress, atomAddress, imageBaseAddress, findSectionAddress); } } } void ArchHandler_arm64::applyFixupFinal(const Reference &ref, uint8_t *loc, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress, uint64_t imageBaseAddress, FindAddressForAtom findSectionAddress) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return; assert(ref.kindArch() == Reference::KindArch::AArch64); ulittle32_t *loc32 = reinterpret_cast(loc); ulittle64_t *loc64 = reinterpret_cast(loc); int32_t displacement; uint32_t instruction; uint32_t value32; uint32_t value64; switch (static_cast(ref.kindValue())) { case branch26: displacement = (targetAddress - fixupAddress) + ref.addend(); *loc32 = setDisplacementInBranch26(*loc32, displacement); return; case page21: case gotPage21: case tlvPage21: displacement = ((targetAddress + ref.addend()) & (-4096)) - (fixupAddress & (-4096)); *loc32 = setDisplacementInADRP(*loc32, displacement); return; case offset12: case gotOffset12: case tlvOffset12: displacement = (targetAddress + ref.addend()) & 0x00000FFF; *loc32 = setImm12(*loc32, displacement); return; case offset12scale2: displacement = (targetAddress + ref.addend()) & 0x00000FFF; assert(((displacement & 0x1) == 0) && "scaled imm12 not accessing 2-byte aligneds"); *loc32 = setImm12(*loc32, displacement >> 1); return; case offset12scale4: displacement = (targetAddress + ref.addend()) & 0x00000FFF; assert(((displacement & 0x3) == 0) && "scaled imm12 not accessing 4-byte aligned"); *loc32 = setImm12(*loc32, displacement >> 2); return; case offset12scale8: displacement = (targetAddress + ref.addend()) & 0x00000FFF; assert(((displacement & 0x7) == 0) && "scaled imm12 not accessing 8-byte aligned"); *loc32 = setImm12(*loc32, displacement >> 3); return; case offset12scale16: displacement = (targetAddress + ref.addend()) & 0x00000FFF; assert(((displacement & 0xF) == 0) && "scaled imm12 not accessing 16-byte aligned"); *loc32 = setImm12(*loc32, displacement >> 4); return; case addOffset12: instruction = *loc32; assert(((instruction & 0xFFC00000) == 0xF9400000) && "GOT reloc is not an LDR instruction"); displacement = (targetAddress + ref.addend()) & 0x00000FFF; value32 = 0x91000000 | (instruction & 0x000003FF); instruction = setImm12(value32, displacement); *loc32 = instruction; return; case pointer64: case pointer64ToGOT: *loc64 = targetAddress + ref.addend(); return; case delta64: case unwindFDEToFunction: *loc64 = (targetAddress - fixupAddress) + ref.addend(); return; case delta32: case delta32ToGOT: case unwindCIEToPersonalityFunction: *loc32 = (targetAddress - fixupAddress) + ref.addend(); return; case negDelta32: *loc32 = fixupAddress - targetAddress + ref.addend(); return; case lazyPointer: // Do nothing return; case lazyImmediateLocation: *loc32 = ref.addend(); return; case imageOffset: *loc32 = (targetAddress - imageBaseAddress) + ref.addend(); return; case imageOffsetGot: llvm_unreachable("imageOffsetGot should have been changed to imageOffset"); break; case unwindInfoToEhFrame: value64 = targetAddress - findSectionAddress(*ref.target()) + ref.addend(); assert(value64 < 0xffffffU && "offset in __eh_frame too large"); *loc32 = (*loc32 & 0xff000000U) | value64; return; case invalid: // Fall into llvm_unreachable(). break; } llvm_unreachable("invalid arm64 Reference Kind"); } void ArchHandler_arm64::applyFixupRelocatable(const Reference &ref, uint8_t *loc, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress, bool targetUnnamed) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return; assert(ref.kindArch() == Reference::KindArch::AArch64); ulittle32_t *loc32 = reinterpret_cast(loc); ulittle64_t *loc64 = reinterpret_cast(loc); switch (static_cast(ref.kindValue())) { case branch26: *loc32 = setDisplacementInBranch26(*loc32, 0); return; case page21: case gotPage21: case tlvPage21: *loc32 = setDisplacementInADRP(*loc32, 0); return; case offset12: case offset12scale2: case offset12scale4: case offset12scale8: case offset12scale16: case gotOffset12: case tlvOffset12: *loc32 = setImm12(*loc32, 0); return; case pointer64: if (targetUnnamed) *loc64 = targetAddress + ref.addend(); else *loc64 = ref.addend(); return; case delta64: *loc64 = ref.addend() + inAtomAddress - fixupAddress; return; case unwindFDEToFunction: // We don't emit unwindFDEToFunction in -r mode as they are implicitly // generated from the data in the __eh_frame section. So here we need // to use the targetAddress so that we can generate the full relocation // when we parse again later. *loc64 = targetAddress - fixupAddress; return; case delta32: *loc32 = ref.addend() + inAtomAddress - fixupAddress; return; case negDelta32: // We don't emit negDelta32 in -r mode as they are implicitly // generated from the data in the __eh_frame section. So here we need // to use the targetAddress so that we can generate the full relocation // when we parse again later. *loc32 = fixupAddress - targetAddress + ref.addend(); return; case pointer64ToGOT: *loc64 = 0; return; case delta32ToGOT: *loc32 = inAtomAddress - fixupAddress; return; case unwindCIEToPersonalityFunction: // We don't emit unwindCIEToPersonalityFunction in -r mode as they are // implicitly generated from the data in the __eh_frame section. So here we // need to use the targetAddress so that we can generate the full relocation // when we parse again later. *loc32 = targetAddress - fixupAddress; return; case addOffset12: llvm_unreachable("lazy reference kind implies GOT pass was run"); case lazyPointer: case lazyImmediateLocation: llvm_unreachable("lazy reference kind implies Stubs pass was run"); case imageOffset: case imageOffsetGot: case unwindInfoToEhFrame: llvm_unreachable("fixup implies __unwind_info"); return; case invalid: // Fall into llvm_unreachable(). break; } llvm_unreachable("unknown arm64 Reference Kind"); } void ArchHandler_arm64::appendSectionRelocations( const DefinedAtom &atom, uint64_t atomSectionOffset, const Reference &ref, FindSymbolIndexForAtom symbolIndexForAtom, FindSectionIndexForAtom sectionIndexForAtom, FindAddressForAtom addressForAtom, normalized::Relocations &relocs) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return; assert(ref.kindArch() == Reference::KindArch::AArch64); uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom(); switch (static_cast(ref.kindValue())) { case branch26: if (ref.addend()) { appendReloc(relocs, sectionOffset, ref.addend(), 0, ARM64_RELOC_ADDEND | rLength4); appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4); } else { appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4); } return; case page21: if (ref.addend()) { appendReloc(relocs, sectionOffset, ref.addend(), 0, ARM64_RELOC_ADDEND | rLength4); appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4); } else { appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4); } return; case offset12: case offset12scale2: case offset12scale4: case offset12scale8: case offset12scale16: if (ref.addend()) { appendReloc(relocs, sectionOffset, ref.addend(), 0, ARM64_RELOC_ADDEND | rLength4); appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_PAGEOFF12 | rExtern | rLength4); } else { appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_PAGEOFF12 | rExtern | rLength4); } return; case gotPage21: assert(ref.addend() == 0); appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_GOT_LOAD_PAGE21 | rPcRel | rExtern | rLength4); return; case gotOffset12: assert(ref.addend() == 0); appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_GOT_LOAD_PAGEOFF12 | rExtern | rLength4); return; case tlvPage21: assert(ref.addend() == 0); appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_TLVP_LOAD_PAGE21 | rPcRel | rExtern | rLength4); return; case tlvOffset12: assert(ref.addend() == 0); appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_TLVP_LOAD_PAGEOFF12 | rExtern | rLength4); return; case pointer64: if (ref.target()->name().empty()) appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, ARM64_RELOC_UNSIGNED | rLength8); else appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_UNSIGNED | rExtern | rLength8); return; case delta64: appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0, ARM64_RELOC_SUBTRACTOR | rExtern | rLength8); appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_UNSIGNED | rExtern | rLength8); return; case delta32: appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0, ARM64_RELOC_SUBTRACTOR | rExtern | rLength4 ); appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_UNSIGNED | rExtern | rLength4 ); return; case pointer64ToGOT: assert(ref.addend() == 0); appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_POINTER_TO_GOT | rExtern | rLength8); return; case delta32ToGOT: assert(ref.addend() == 0); appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, ARM64_RELOC_POINTER_TO_GOT | rPcRel | rExtern | rLength4); return; case addOffset12: llvm_unreachable("lazy reference kind implies GOT pass was run"); case lazyPointer: case lazyImmediateLocation: llvm_unreachable("lazy reference kind implies Stubs pass was run"); case imageOffset: case imageOffsetGot: llvm_unreachable("deltas from mach_header can only be in final images"); case unwindCIEToPersonalityFunction: case unwindFDEToFunction: case unwindInfoToEhFrame: case negDelta32: // Do nothing. return; case invalid: // Fall into llvm_unreachable(). break; } llvm_unreachable("unknown arm64 Reference Kind"); } std::unique_ptr ArchHandler::create_arm64() { return std::unique_ptr(new ArchHandler_arm64()); } } // namespace mach_o } // namespace lld Index: head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp =================================================================== --- head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp (revision 326908) +++ head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp (revision 326909) @@ -1,640 +1,644 @@ //===- lib/FileFormat/MachO/ArchHandler_x86.cpp ---------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "ArchHandler.h" #include "Atoms.h" #include "MachONormalizedFileBinaryUtils.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm::MachO; using namespace lld::mach_o::normalized; namespace lld { namespace mach_o { using llvm::support::ulittle16_t; using llvm::support::ulittle32_t; using llvm::support::little16_t; using llvm::support::little32_t; class ArchHandler_x86 : public ArchHandler { public: ArchHandler_x86() = default; ~ArchHandler_x86() override = default; const Registry::KindStrings *kindStrings() override { return _sKindStrings; } Reference::KindArch kindArch() override { return Reference::KindArch::x86; } const StubInfo &stubInfo() override { return _sStubInfo; } bool isCallSite(const Reference &) override; bool isNonCallBranch(const Reference &) override { return false; } bool isPointer(const Reference &) override; bool isPairedReloc(const normalized::Relocation &) override; bool needsCompactUnwind() override { return false; } Reference::KindValue imageOffsetKind() override { return invalid; } Reference::KindValue imageOffsetKindIndirect() override { return invalid; } Reference::KindValue unwindRefToPersonalityFunctionKind() override { return invalid; } Reference::KindValue unwindRefToCIEKind() override { return negDelta32; } Reference::KindValue unwindRefToFunctionKind() override{ return delta32; } + Reference::KindValue lazyImmediateLocationKind() override { + return lazyImmediateLocation; + } + Reference::KindValue unwindRefToEhFrameKind() override { return invalid; } Reference::KindValue pointerKind() override { return invalid; } uint32_t dwarfCompactUnwindType() override { return 0x04000000U; } llvm::Error getReferenceInfo(const normalized::Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool swap, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) override; llvm::Error getPairReferenceInfo(const normalized::Relocation &reloc1, const normalized::Relocation &reloc2, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool swap, bool scatterable, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) override; void generateAtomContent(const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress, FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress, llvm::MutableArrayRef atomContentBuffer) override; void appendSectionRelocations(const DefinedAtom &atom, uint64_t atomSectionOffset, const Reference &ref, FindSymbolIndexForAtom symbolIndexForAtom, FindSectionIndexForAtom sectionIndexForAtom, FindAddressForAtom addressForAtom, normalized::Relocations &relocs) override; bool isDataInCodeTransition(Reference::KindValue refKind) override { return refKind == modeCode || refKind == modeData; } Reference::KindValue dataInCodeTransitionStart( const MachODefinedAtom &atom) override { return modeData; } Reference::KindValue dataInCodeTransitionEnd( const MachODefinedAtom &atom) override { return modeCode; } private: static const Registry::KindStrings _sKindStrings[]; static const StubInfo _sStubInfo; enum X86Kind : Reference::KindValue { invalid, /// for error condition modeCode, /// Content starting at this offset is code. modeData, /// Content starting at this offset is data. // Kinds found in mach-o .o files: branch32, /// ex: call _foo branch16, /// ex: callw _foo abs32, /// ex: movl _foo, %eax funcRel32, /// ex: movl _foo-L1(%eax), %eax pointer32, /// ex: .long _foo delta32, /// ex: .long _foo - . negDelta32, /// ex: .long . - _foo // Kinds introduced by Passes: lazyPointer, /// Location contains a lazy pointer. lazyImmediateLocation, /// Location contains immediate value used in stub. }; static bool useExternalRelocationTo(const Atom &target); void applyFixupFinal(const Reference &ref, uint8_t *location, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress); void applyFixupRelocatable(const Reference &ref, uint8_t *location, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress); }; //===----------------------------------------------------------------------===// // ArchHandler_x86 //===----------------------------------------------------------------------===// const Registry::KindStrings ArchHandler_x86::_sKindStrings[] = { LLD_KIND_STRING_ENTRY(invalid), LLD_KIND_STRING_ENTRY(modeCode), LLD_KIND_STRING_ENTRY(modeData), LLD_KIND_STRING_ENTRY(branch32), LLD_KIND_STRING_ENTRY(branch16), LLD_KIND_STRING_ENTRY(abs32), LLD_KIND_STRING_ENTRY(funcRel32), LLD_KIND_STRING_ENTRY(pointer32), LLD_KIND_STRING_ENTRY(delta32), LLD_KIND_STRING_ENTRY(negDelta32), LLD_KIND_STRING_ENTRY(lazyPointer), LLD_KIND_STRING_ENTRY(lazyImmediateLocation), LLD_KIND_STRING_END }; const ArchHandler::StubInfo ArchHandler_x86::_sStubInfo = { "dyld_stub_binder", // Lazy pointer references { Reference::KindArch::x86, pointer32, 0, 0 }, { Reference::KindArch::x86, lazyPointer, 0, 0 }, // GOT pointer to dyld_stub_binder { Reference::KindArch::x86, pointer32, 0, 0 }, // x86 code alignment 1, // Stub size and code 6, { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 }, // jmp *lazyPointer { Reference::KindArch::x86, abs32, 2, 0 }, { false, 0, 0, 0 }, // Stub Helper size and code 10, { 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $lazy-info-offset 0xE9, 0x00, 0x00, 0x00, 0x00 }, // jmp helperhelper { Reference::KindArch::x86, lazyImmediateLocation, 1, 0 }, { Reference::KindArch::x86, branch32, 6, 0 }, // Stub helper image cache content type DefinedAtom::typeNonLazyPointer, // Stub Helper-Common size and code 12, // Stub helper alignment 2, { 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $dyld_ImageLoaderCache 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *_fast_lazy_bind 0x90 }, // nop { Reference::KindArch::x86, abs32, 1, 0 }, { false, 0, 0, 0 }, { Reference::KindArch::x86, abs32, 7, 0 }, { false, 0, 0, 0 } }; bool ArchHandler_x86::isCallSite(const Reference &ref) { return (ref.kindValue() == branch32); } bool ArchHandler_x86::isPointer(const Reference &ref) { return (ref.kindValue() == pointer32); } bool ArchHandler_x86::isPairedReloc(const Relocation &reloc) { if (!reloc.scattered) return false; return (reloc.type == GENERIC_RELOC_LOCAL_SECTDIFF) || (reloc.type == GENERIC_RELOC_SECTDIFF); } llvm::Error ArchHandler_x86::getReferenceInfo(const Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool swap, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) { DefinedAtom::ContentPermissions perms; const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom]; uint64_t targetAddress; switch (relocPattern(reloc)) { case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength4: // ex: call _foo (and _foo undefined) *kind = branch32; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = fixupAddress + 4 + (int32_t)*(const little32_t *)fixupContent; break; case GENERIC_RELOC_VANILLA | rPcRel | rLength4: // ex: call _foo (and _foo defined) *kind = branch32; targetAddress = fixupAddress + 4 + (int32_t) * (const little32_t *)fixupContent; return atomFromAddress(reloc.symbol, targetAddress, target, addend); break; case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4: // ex: call _foo+n (and _foo defined) *kind = branch32; targetAddress = fixupAddress + 4 + (int32_t) * (const little32_t *)fixupContent; if (auto ec = atomFromAddress(0, reloc.value, target, addend)) return ec; *addend = targetAddress - reloc.value; break; case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2: // ex: callw _foo (and _foo undefined) *kind = branch16; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = fixupAddress + 2 + (int16_t)*(const little16_t *)fixupContent; break; case GENERIC_RELOC_VANILLA | rPcRel | rLength2: // ex: callw _foo (and _foo defined) *kind = branch16; targetAddress = fixupAddress + 2 + (int16_t) * (const little16_t *)fixupContent; return atomFromAddress(reloc.symbol, targetAddress, target, addend); break; case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2: // ex: callw _foo+n (and _foo defined) *kind = branch16; targetAddress = fixupAddress + 2 + (int16_t) * (const little16_t *)fixupContent; if (auto ec = atomFromAddress(0, reloc.value, target, addend)) return ec; *addend = targetAddress - reloc.value; break; case GENERIC_RELOC_VANILLA | rExtern | rLength4: // ex: movl _foo, %eax (and _foo undefined) // ex: .long _foo (and _foo undefined) perms = inAtom->permissions(); *kind = ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32 : pointer32; if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = *(const ulittle32_t *)fixupContent; break; case GENERIC_RELOC_VANILLA | rLength4: // ex: movl _foo, %eax (and _foo defined) // ex: .long _foo (and _foo defined) perms = inAtom->permissions(); *kind = ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32 : pointer32; targetAddress = *(const ulittle32_t *)fixupContent; return atomFromAddress(reloc.symbol, targetAddress, target, addend); break; case GENERIC_RELOC_VANILLA | rScattered | rLength4: // ex: .long _foo+n (and _foo defined) perms = inAtom->permissions(); *kind = ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32 : pointer32; if (auto ec = atomFromAddress(0, reloc.value, target, addend)) return ec; *addend = *(const ulittle32_t *)fixupContent - reloc.value; break; default: return llvm::make_error("unsupported i386 relocation type"); } return llvm::Error::success(); } llvm::Error ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1, const normalized::Relocation &reloc2, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool swap, bool scatterable, FindAtomBySectionAndAddress atomFromAddr, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) { const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom]; DefinedAtom::ContentPermissions perms = inAtom->permissions(); uint32_t fromAddress; uint32_t toAddress; uint32_t value; const lld::Atom *fromTarget; Reference::Addend offsetInTo; Reference::Addend offsetInFrom; switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) { case ((GENERIC_RELOC_SECTDIFF | rScattered | rLength4) << 16 | GENERIC_RELOC_PAIR | rScattered | rLength4): case ((GENERIC_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 | GENERIC_RELOC_PAIR | rScattered | rLength4): toAddress = reloc1.value; fromAddress = reloc2.value; value = *(const little32_t *)fixupContent; if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo)) return ec; if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom)) return ec; if (fromTarget != inAtom) { if (*target != inAtom) return llvm::make_error( "SECTDIFF relocation where neither target is in atom"); *kind = negDelta32; *addend = toAddress - value - fromAddress; *target = fromTarget; } else { if ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) { // SECTDIFF relocations are used in i386 codegen where the function // prolog does a CALL to the next instruction which POPs the return // address into EBX which becomes the pic-base register. The POP // instruction is label the used for the subtrahend in expressions. // The funcRel32 kind represents the 32-bit delta to some symbol from // the start of the function (atom) containing the funcRel32. *kind = funcRel32; uint32_t ta = fromAddress + value - toAddress; *addend = ta - offsetInFrom; } else { *kind = delta32; *addend = fromAddress + value - toAddress; } } return llvm::Error::success(); break; default: return llvm::make_error("unsupported i386 relocation type"); } } void ArchHandler_x86::generateAtomContent(const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress, FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress, llvm::MutableArrayRef atomContentBuffer) { // Copy raw bytes. std::copy(atom.rawContent().begin(), atom.rawContent().end(), atomContentBuffer.begin()); // Apply fix-ups. for (const Reference *ref : atom) { uint32_t offset = ref->offsetInAtom(); const Atom *target = ref->target(); uint64_t targetAddress = 0; if (isa(target)) targetAddress = findAddress(*target); uint64_t atomAddress = findAddress(atom); uint64_t fixupAddress = atomAddress + offset; if (relocatable) { applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress, targetAddress, atomAddress); } else { applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress, targetAddress, atomAddress); } } } void ArchHandler_x86::applyFixupFinal(const Reference &ref, uint8_t *loc, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return; assert(ref.kindArch() == Reference::KindArch::x86); ulittle32_t *loc32 = reinterpret_cast(loc); switch (static_cast(ref.kindValue())) { case branch32: *loc32 = (targetAddress - (fixupAddress + 4)) + ref.addend(); break; case branch16: *loc32 = (targetAddress - (fixupAddress + 2)) + ref.addend(); break; case pointer32: case abs32: *loc32 = targetAddress + ref.addend(); break; case funcRel32: *loc32 = targetAddress - inAtomAddress + ref.addend(); break; case delta32: *loc32 = targetAddress - fixupAddress + ref.addend(); break; case negDelta32: *loc32 = fixupAddress - targetAddress + ref.addend(); break; case modeCode: case modeData: case lazyPointer: // do nothing break; case lazyImmediateLocation: *loc32 = ref.addend(); break; case invalid: llvm_unreachable("invalid x86 Reference Kind"); break; } } void ArchHandler_x86::applyFixupRelocatable(const Reference &ref, uint8_t *loc, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return; assert(ref.kindArch() == Reference::KindArch::x86); bool useExternalReloc = useExternalRelocationTo(*ref.target()); ulittle16_t *loc16 = reinterpret_cast(loc); ulittle32_t *loc32 = reinterpret_cast(loc); switch (static_cast(ref.kindValue())) { case branch32: if (useExternalReloc) *loc32 = ref.addend() - (fixupAddress + 4); else *loc32 =(targetAddress - (fixupAddress+4)) + ref.addend(); break; case branch16: if (useExternalReloc) *loc16 = ref.addend() - (fixupAddress + 2); else *loc16 = (targetAddress - (fixupAddress+2)) + ref.addend(); break; case pointer32: case abs32: *loc32 = targetAddress + ref.addend(); break; case funcRel32: *loc32 = targetAddress - inAtomAddress + ref.addend(); // FIXME break; case delta32: *loc32 = targetAddress - fixupAddress + ref.addend(); break; case negDelta32: *loc32 = fixupAddress - targetAddress + ref.addend(); break; case modeCode: case modeData: case lazyPointer: case lazyImmediateLocation: // do nothing break; case invalid: llvm_unreachable("invalid x86 Reference Kind"); break; } } bool ArchHandler_x86::useExternalRelocationTo(const Atom &target) { // Undefined symbols are referenced via external relocations. if (isa(&target)) return true; if (const DefinedAtom *defAtom = dyn_cast(&target)) { switch (defAtom->merge()) { case DefinedAtom::mergeAsTentative: // Tentative definitions are referenced via external relocations. return true; case DefinedAtom::mergeAsWeak: case DefinedAtom::mergeAsWeakAndAddressUsed: // Global weak-defs are referenced via external relocations. return (defAtom->scope() == DefinedAtom::scopeGlobal); default: break; } } // Everything else is reference via an internal relocation. return false; } void ArchHandler_x86::appendSectionRelocations( const DefinedAtom &atom, uint64_t atomSectionOffset, const Reference &ref, FindSymbolIndexForAtom symbolIndexForAtom, FindSectionIndexForAtom sectionIndexForAtom, FindAddressForAtom addressForAtom, normalized::Relocations &relocs) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return; assert(ref.kindArch() == Reference::KindArch::x86); uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom(); bool useExternalReloc = useExternalRelocationTo(*ref.target()); switch (static_cast(ref.kindValue())) { case modeCode: case modeData: break; case branch32: if (useExternalReloc) { appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, GENERIC_RELOC_VANILLA | rExtern | rPcRel | rLength4); } else { if (ref.addend() != 0) appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4); else appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0, GENERIC_RELOC_VANILLA | rPcRel | rLength4); } break; case branch16: if (useExternalReloc) { appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, GENERIC_RELOC_VANILLA | rExtern | rPcRel | rLength2); } else { if (ref.addend() != 0) appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2); else appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0, GENERIC_RELOC_VANILLA | rPcRel | rLength2); } break; case pointer32: case abs32: if (useExternalReloc) appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, GENERIC_RELOC_VANILLA | rExtern | rLength4); else { if (ref.addend() != 0) appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), GENERIC_RELOC_VANILLA | rScattered | rLength4); else appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, GENERIC_RELOC_VANILLA | rLength4); } break; case funcRel32: appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), GENERIC_RELOC_SECTDIFF | rScattered | rLength4); appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) - ref.addend(), GENERIC_RELOC_PAIR | rScattered | rLength4); break; case delta32: appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), GENERIC_RELOC_SECTDIFF | rScattered | rLength4); appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) + ref.offsetInAtom(), GENERIC_RELOC_PAIR | rScattered | rLength4); break; case negDelta32: appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) + ref.offsetInAtom(), GENERIC_RELOC_SECTDIFF | rScattered | rLength4); appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), GENERIC_RELOC_PAIR | rScattered | rLength4); break; case lazyPointer: case lazyImmediateLocation: llvm_unreachable("lazy reference kind implies Stubs pass was run"); break; case invalid: llvm_unreachable("unknown x86 Reference Kind"); break; } } std::unique_ptr ArchHandler::create_x86() { return std::unique_ptr(new ArchHandler_x86()); } } // namespace mach_o } // namespace lld Index: head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp =================================================================== --- head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp (revision 326908) +++ head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp (revision 326909) @@ -1,861 +1,865 @@ //===- lib/FileFormat/MachO/ArchHandler_x86_64.cpp ------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "ArchHandler.h" #include "Atoms.h" #include "MachONormalizedFileBinaryUtils.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm::MachO; using namespace lld::mach_o::normalized; namespace lld { namespace mach_o { using llvm::support::ulittle32_t; using llvm::support::ulittle64_t; using llvm::support::little32_t; using llvm::support::little64_t; class ArchHandler_x86_64 : public ArchHandler { public: ArchHandler_x86_64() = default; ~ArchHandler_x86_64() override = default; const Registry::KindStrings *kindStrings() override { return _sKindStrings; } Reference::KindArch kindArch() override { return Reference::KindArch::x86_64; } /// Used by GOTPass to locate GOT References bool isGOTAccess(const Reference &ref, bool &canBypassGOT) override { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return false; assert(ref.kindArch() == Reference::KindArch::x86_64); switch (ref.kindValue()) { case ripRel32GotLoad: canBypassGOT = true; return true; case ripRel32Got: canBypassGOT = false; return true; case imageOffsetGot: canBypassGOT = false; return true; default: return false; } } bool isTLVAccess(const Reference &ref) const override { assert(ref.kindNamespace() == Reference::KindNamespace::mach_o); assert(ref.kindArch() == Reference::KindArch::x86_64); return ref.kindValue() == ripRel32Tlv; } void updateReferenceToTLV(const Reference *ref) override { assert(ref->kindNamespace() == Reference::KindNamespace::mach_o); assert(ref->kindArch() == Reference::KindArch::x86_64); assert(ref->kindValue() == ripRel32Tlv); const_cast(ref)->setKindValue(ripRel32); } /// Used by GOTPass to update GOT References void updateReferenceToGOT(const Reference *ref, bool targetNowGOT) override { assert(ref->kindNamespace() == Reference::KindNamespace::mach_o); assert(ref->kindArch() == Reference::KindArch::x86_64); switch (ref->kindValue()) { case ripRel32Got: assert(targetNowGOT && "target must be GOT"); case ripRel32GotLoad: const_cast(ref) ->setKindValue(targetNowGOT ? ripRel32 : ripRel32GotLoadNowLea); break; case imageOffsetGot: const_cast(ref)->setKindValue(imageOffset); break; default: llvm_unreachable("unknown GOT reference kind"); } } bool needsCompactUnwind() override { return true; } Reference::KindValue imageOffsetKind() override { return imageOffset; } Reference::KindValue imageOffsetKindIndirect() override { return imageOffsetGot; } Reference::KindValue unwindRefToPersonalityFunctionKind() override { return ripRel32Got; } Reference::KindValue unwindRefToCIEKind() override { return negDelta32; } Reference::KindValue unwindRefToFunctionKind() override{ return unwindFDEToFunction; } + Reference::KindValue lazyImmediateLocationKind() override { + return lazyImmediateLocation; + } + Reference::KindValue unwindRefToEhFrameKind() override { return unwindInfoToEhFrame; } Reference::KindValue pointerKind() override { return pointer64; } uint32_t dwarfCompactUnwindType() override { return 0x04000000U; } const StubInfo &stubInfo() override { return _sStubInfo; } bool isNonCallBranch(const Reference &) override { return false; } bool isCallSite(const Reference &) override; bool isPointer(const Reference &) override; bool isPairedReloc(const normalized::Relocation &) override; llvm::Error getReferenceInfo(const normalized::Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool swap, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) override; llvm::Error getPairReferenceInfo(const normalized::Relocation &reloc1, const normalized::Relocation &reloc2, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool swap, bool scatterable, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) override; bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) override { return (atom->contentType() == DefinedAtom::typeCString); } void generateAtomContent(const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress, FindAddressForAtom findSectionAddress, uint64_t imageBase, llvm::MutableArrayRef atomContentBuffer) override; void appendSectionRelocations(const DefinedAtom &atom, uint64_t atomSectionOffset, const Reference &ref, FindSymbolIndexForAtom symbolIndexForAtom, FindSectionIndexForAtom sectionIndexForAtom, FindAddressForAtom addressForAtom, normalized::Relocations &relocs) override; private: static const Registry::KindStrings _sKindStrings[]; static const StubInfo _sStubInfo; enum X86_64Kind: Reference::KindValue { invalid, /// for error condition // Kinds found in mach-o .o files: branch32, /// ex: call _foo ripRel32, /// ex: movq _foo(%rip), %rax ripRel32Minus1, /// ex: movb $0x12, _foo(%rip) ripRel32Minus2, /// ex: movw $0x1234, _foo(%rip) ripRel32Minus4, /// ex: movl $0x12345678, _foo(%rip) ripRel32Anon, /// ex: movq L1(%rip), %rax ripRel32Minus1Anon, /// ex: movb $0x12, L1(%rip) ripRel32Minus2Anon, /// ex: movw $0x1234, L1(%rip) ripRel32Minus4Anon, /// ex: movw $0x12345678, L1(%rip) ripRel32GotLoad, /// ex: movq _foo@GOTPCREL(%rip), %rax ripRel32Got, /// ex: pushq _foo@GOTPCREL(%rip) ripRel32Tlv, /// ex: movq _foo@TLVP(%rip), %rdi pointer64, /// ex: .quad _foo pointer64Anon, /// ex: .quad L1 delta64, /// ex: .quad _foo - . delta32, /// ex: .long _foo - . delta64Anon, /// ex: .quad L1 - . delta32Anon, /// ex: .long L1 - . negDelta64, /// ex: .quad . - _foo negDelta32, /// ex: .long . - _foo // Kinds introduced by Passes: ripRel32GotLoadNowLea, /// Target of GOT load is in linkage unit so /// "movq _foo@GOTPCREL(%rip), %rax" can be changed /// to "leaq _foo(%rip), %rax lazyPointer, /// Location contains a lazy pointer. lazyImmediateLocation, /// Location contains immediate value used in stub. imageOffset, /// Location contains offset of atom in final image imageOffsetGot, /// Location contains offset of GOT entry for atom in /// final image (typically personality function). unwindFDEToFunction, /// Nearly delta64, but cannot be rematerialized in /// relocatable object (yay for implicit contracts!). unwindInfoToEhFrame, /// Fix low 24 bits of compact unwind encoding to /// refer to __eh_frame entry. tlvInitSectionOffset /// Location contains offset tlv init-value atom /// within the __thread_data section. }; Reference::KindValue kindFromReloc(const normalized::Relocation &reloc); void applyFixupFinal(const Reference &ref, uint8_t *location, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress, uint64_t imageBaseAddress, FindAddressForAtom findSectionAddress); void applyFixupRelocatable(const Reference &ref, uint8_t *location, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress); }; const Registry::KindStrings ArchHandler_x86_64::_sKindStrings[] = { LLD_KIND_STRING_ENTRY(invalid), LLD_KIND_STRING_ENTRY(branch32), LLD_KIND_STRING_ENTRY(ripRel32), LLD_KIND_STRING_ENTRY(ripRel32Minus1), LLD_KIND_STRING_ENTRY(ripRel32Minus2), LLD_KIND_STRING_ENTRY(ripRel32Minus4), LLD_KIND_STRING_ENTRY(ripRel32Anon), LLD_KIND_STRING_ENTRY(ripRel32Minus1Anon), LLD_KIND_STRING_ENTRY(ripRel32Minus2Anon), LLD_KIND_STRING_ENTRY(ripRel32Minus4Anon), LLD_KIND_STRING_ENTRY(ripRel32GotLoad), LLD_KIND_STRING_ENTRY(ripRel32GotLoadNowLea), LLD_KIND_STRING_ENTRY(ripRel32Got), LLD_KIND_STRING_ENTRY(ripRel32Tlv), LLD_KIND_STRING_ENTRY(lazyPointer), LLD_KIND_STRING_ENTRY(lazyImmediateLocation), LLD_KIND_STRING_ENTRY(pointer64), LLD_KIND_STRING_ENTRY(pointer64Anon), LLD_KIND_STRING_ENTRY(delta32), LLD_KIND_STRING_ENTRY(delta64), LLD_KIND_STRING_ENTRY(delta32Anon), LLD_KIND_STRING_ENTRY(delta64Anon), LLD_KIND_STRING_ENTRY(negDelta64), LLD_KIND_STRING_ENTRY(negDelta32), LLD_KIND_STRING_ENTRY(imageOffset), LLD_KIND_STRING_ENTRY(imageOffsetGot), LLD_KIND_STRING_ENTRY(unwindFDEToFunction), LLD_KIND_STRING_ENTRY(unwindInfoToEhFrame), LLD_KIND_STRING_ENTRY(tlvInitSectionOffset), LLD_KIND_STRING_END }; const ArchHandler::StubInfo ArchHandler_x86_64::_sStubInfo = { "dyld_stub_binder", // Lazy pointer references { Reference::KindArch::x86_64, pointer64, 0, 0 }, { Reference::KindArch::x86_64, lazyPointer, 0, 0 }, // GOT pointer to dyld_stub_binder { Reference::KindArch::x86_64, pointer64, 0, 0 }, // x86_64 code alignment 2^1 1, // Stub size and code 6, { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 }, // jmp *lazyPointer { Reference::KindArch::x86_64, ripRel32, 2, 0 }, { false, 0, 0, 0 }, // Stub Helper size and code 10, { 0x68, 0x00, 0x00, 0x00, 0x00, // pushq $lazy-info-offset 0xE9, 0x00, 0x00, 0x00, 0x00 }, // jmp helperhelper { Reference::KindArch::x86_64, lazyImmediateLocation, 1, 0 }, { Reference::KindArch::x86_64, branch32, 6, 0 }, // Stub helper image cache content type DefinedAtom::typeNonLazyPointer, // Stub Helper-Common size and code 16, // Stub helper alignment 2, { 0x4C, 0x8D, 0x1D, 0x00, 0x00, 0x00, 0x00, // leaq cache(%rip),%r11 0x41, 0x53, // push %r11 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *binder(%rip) 0x90 }, // nop { Reference::KindArch::x86_64, ripRel32, 3, 0 }, { false, 0, 0, 0 }, { Reference::KindArch::x86_64, ripRel32, 11, 0 }, { false, 0, 0, 0 } }; bool ArchHandler_x86_64::isCallSite(const Reference &ref) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return false; assert(ref.kindArch() == Reference::KindArch::x86_64); return (ref.kindValue() == branch32); } bool ArchHandler_x86_64::isPointer(const Reference &ref) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return false; assert(ref.kindArch() == Reference::KindArch::x86_64); Reference::KindValue kind = ref.kindValue(); return (kind == pointer64 || kind == pointer64Anon); } bool ArchHandler_x86_64::isPairedReloc(const Relocation &reloc) { return (reloc.type == X86_64_RELOC_SUBTRACTOR); } Reference::KindValue ArchHandler_x86_64::kindFromReloc(const Relocation &reloc) { switch(relocPattern(reloc)) { case X86_64_RELOC_BRANCH | rPcRel | rExtern | rLength4: return branch32; case X86_64_RELOC_SIGNED | rPcRel | rExtern | rLength4: return ripRel32; case X86_64_RELOC_SIGNED | rPcRel | rLength4: return ripRel32Anon; case X86_64_RELOC_SIGNED_1 | rPcRel | rExtern | rLength4: return ripRel32Minus1; case X86_64_RELOC_SIGNED_1 | rPcRel | rLength4: return ripRel32Minus1Anon; case X86_64_RELOC_SIGNED_2 | rPcRel | rExtern | rLength4: return ripRel32Minus2; case X86_64_RELOC_SIGNED_2 | rPcRel | rLength4: return ripRel32Minus2Anon; case X86_64_RELOC_SIGNED_4 | rPcRel | rExtern | rLength4: return ripRel32Minus4; case X86_64_RELOC_SIGNED_4 | rPcRel | rLength4: return ripRel32Minus4Anon; case X86_64_RELOC_GOT_LOAD | rPcRel | rExtern | rLength4: return ripRel32GotLoad; case X86_64_RELOC_GOT | rPcRel | rExtern | rLength4: return ripRel32Got; case X86_64_RELOC_TLV | rPcRel | rExtern | rLength4: return ripRel32Tlv; case X86_64_RELOC_UNSIGNED | rExtern | rLength8: return pointer64; case X86_64_RELOC_UNSIGNED | rLength8: return pointer64Anon; default: return invalid; } } llvm::Error ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool swap, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) { *kind = kindFromReloc(reloc); if (*kind == invalid) return llvm::make_error("unknown type"); const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom]; uint64_t targetAddress; switch (*kind) { case branch32: case ripRel32: if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = *(const little32_t *)fixupContent; return llvm::Error::success(); case ripRel32Minus1: if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = (int32_t)*(const little32_t *)fixupContent + 1; return llvm::Error::success(); case ripRel32Minus2: if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = (int32_t)*(const little32_t *)fixupContent + 2; return llvm::Error::success(); case ripRel32Minus4: if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = (int32_t)*(const little32_t *)fixupContent + 4; return llvm::Error::success(); case ripRel32Anon: targetAddress = fixupAddress + 4 + *(const little32_t *)fixupContent; return atomFromAddress(reloc.symbol, targetAddress, target, addend); case ripRel32Minus1Anon: targetAddress = fixupAddress + 5 + *(const little32_t *)fixupContent; return atomFromAddress(reloc.symbol, targetAddress, target, addend); case ripRel32Minus2Anon: targetAddress = fixupAddress + 6 + *(const little32_t *)fixupContent; return atomFromAddress(reloc.symbol, targetAddress, target, addend); case ripRel32Minus4Anon: targetAddress = fixupAddress + 8 + *(const little32_t *)fixupContent; return atomFromAddress(reloc.symbol, targetAddress, target, addend); case ripRel32GotLoad: case ripRel32Got: case ripRel32Tlv: if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; *addend = *(const little32_t *)fixupContent; return llvm::Error::success(); case tlvInitSectionOffset: case pointer64: if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; // If this is the 3rd pointer of a tlv-thunk (i.e. the pointer to the TLV's // initial value) we need to handle it specially. if (inAtom->contentType() == DefinedAtom::typeThunkTLV && offsetInAtom == 16) { *kind = tlvInitSectionOffset; assert(*addend == 0 && "TLV-init has non-zero addend?"); } else *addend = *(const little64_t *)fixupContent; return llvm::Error::success(); case pointer64Anon: targetAddress = *(const little64_t *)fixupContent; return atomFromAddress(reloc.symbol, targetAddress, target, addend); default: llvm_unreachable("bad reloc kind"); } } llvm::Error ArchHandler_x86_64::getPairReferenceInfo(const normalized::Relocation &reloc1, const normalized::Relocation &reloc2, const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress, bool swap, bool scatterable, FindAtomBySectionAndAddress atomFromAddress, FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind, const lld::Atom **target, Reference::Addend *addend) { const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom]; uint64_t targetAddress; const lld::Atom *fromTarget; if (auto ec = atomFromSymbolIndex(reloc1.symbol, &fromTarget)) return ec; switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) { case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 | X86_64_RELOC_UNSIGNED | rExtern | rLength8): { if (auto ec = atomFromSymbolIndex(reloc2.symbol, target)) return ec; uint64_t encodedAddend = (int64_t)*(const little64_t *)fixupContent; if (inAtom == fromTarget) { if (inAtom->contentType() == DefinedAtom::typeCFI) *kind = unwindFDEToFunction; else *kind = delta64; *addend = encodedAddend + offsetInAtom; } else if (inAtom == *target) { *kind = negDelta64; *addend = encodedAddend - offsetInAtom; *target = fromTarget; } else return llvm::make_error("Invalid pointer diff"); return llvm::Error::success(); } case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 | X86_64_RELOC_UNSIGNED | rExtern | rLength4): { if (auto ec = atomFromSymbolIndex(reloc2.symbol, target)) return ec; uint32_t encodedAddend = (int32_t)*(const little32_t *)fixupContent; if (inAtom == fromTarget) { *kind = delta32; *addend = encodedAddend + offsetInAtom; } else if (inAtom == *target) { *kind = negDelta32; *addend = encodedAddend - offsetInAtom; *target = fromTarget; } else return llvm::make_error("Invalid pointer diff"); return llvm::Error::success(); } case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 | X86_64_RELOC_UNSIGNED | rLength8): if (fromTarget != inAtom) return llvm::make_error("pointer diff not in base atom"); *kind = delta64Anon; targetAddress = offsetInAtom + (int64_t)*(const little64_t *)fixupContent; return atomFromAddress(reloc2.symbol, targetAddress, target, addend); case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 | X86_64_RELOC_UNSIGNED | rLength4): if (fromTarget != inAtom) return llvm::make_error("pointer diff not in base atom"); *kind = delta32Anon; targetAddress = offsetInAtom + (int32_t)*(const little32_t *)fixupContent; return atomFromAddress(reloc2.symbol, targetAddress, target, addend); default: return llvm::make_error("unknown pair"); } } void ArchHandler_x86_64::generateAtomContent( const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress, FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress, llvm::MutableArrayRef atomContentBuffer) { // Copy raw bytes. std::copy(atom.rawContent().begin(), atom.rawContent().end(), atomContentBuffer.begin()); // Apply fix-ups. for (const Reference *ref : atom) { uint32_t offset = ref->offsetInAtom(); const Atom *target = ref->target(); uint64_t targetAddress = 0; if (isa(target)) targetAddress = findAddress(*target); uint64_t atomAddress = findAddress(atom); uint64_t fixupAddress = atomAddress + offset; if (relocatable) { applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress, targetAddress, atomAddress); } else { applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress, targetAddress, atomAddress, imageBaseAddress, findSectionAddress); } } } void ArchHandler_x86_64::applyFixupFinal( const Reference &ref, uint8_t *loc, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress, uint64_t imageBaseAddress, FindAddressForAtom findSectionAddress) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return; assert(ref.kindArch() == Reference::KindArch::x86_64); ulittle32_t *loc32 = reinterpret_cast(loc); ulittle64_t *loc64 = reinterpret_cast(loc); switch (static_cast(ref.kindValue())) { case branch32: case ripRel32: case ripRel32Anon: case ripRel32Got: case ripRel32GotLoad: case ripRel32Tlv: *loc32 = targetAddress - (fixupAddress + 4) + ref.addend(); return; case pointer64: case pointer64Anon: *loc64 = targetAddress + ref.addend(); return; case tlvInitSectionOffset: *loc64 = targetAddress - findSectionAddress(*ref.target()) + ref.addend(); return; case ripRel32Minus1: case ripRel32Minus1Anon: *loc32 = targetAddress - (fixupAddress + 5) + ref.addend(); return; case ripRel32Minus2: case ripRel32Minus2Anon: *loc32 = targetAddress - (fixupAddress + 6) + ref.addend(); return; case ripRel32Minus4: case ripRel32Minus4Anon: *loc32 = targetAddress - (fixupAddress + 8) + ref.addend(); return; case delta32: case delta32Anon: *loc32 = targetAddress - fixupAddress + ref.addend(); return; case delta64: case delta64Anon: case unwindFDEToFunction: *loc64 = targetAddress - fixupAddress + ref.addend(); return; case ripRel32GotLoadNowLea: // Change MOVQ to LEA assert(loc[-2] == 0x8B); loc[-2] = 0x8D; *loc32 = targetAddress - (fixupAddress + 4) + ref.addend(); return; case negDelta64: *loc64 = fixupAddress - targetAddress + ref.addend(); return; case negDelta32: *loc32 = fixupAddress - targetAddress + ref.addend(); return; case lazyPointer: // Do nothing return; case lazyImmediateLocation: *loc32 = ref.addend(); return; case imageOffset: case imageOffsetGot: *loc32 = (targetAddress - imageBaseAddress) + ref.addend(); return; case unwindInfoToEhFrame: { uint64_t val = targetAddress - findSectionAddress(*ref.target()) + ref.addend(); assert(val < 0xffffffU && "offset in __eh_frame too large"); *loc32 = (*loc32 & 0xff000000U) | val; return; } case invalid: // Fall into llvm_unreachable(). break; } llvm_unreachable("invalid x86_64 Reference Kind"); } void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref, uint8_t *loc, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return; assert(ref.kindArch() == Reference::KindArch::x86_64); ulittle32_t *loc32 = reinterpret_cast(loc); ulittle64_t *loc64 = reinterpret_cast(loc); switch (static_cast(ref.kindValue())) { case branch32: case ripRel32: case ripRel32Got: case ripRel32GotLoad: case ripRel32Tlv: *loc32 = ref.addend(); return; case ripRel32Anon: *loc32 = (targetAddress - (fixupAddress + 4)) + ref.addend(); return; case tlvInitSectionOffset: case pointer64: *loc64 = ref.addend(); return; case pointer64Anon: *loc64 = targetAddress + ref.addend(); return; case ripRel32Minus1: *loc32 = ref.addend() - 1; return; case ripRel32Minus1Anon: *loc32 = (targetAddress - (fixupAddress + 5)) + ref.addend(); return; case ripRel32Minus2: *loc32 = ref.addend() - 2; return; case ripRel32Minus2Anon: *loc32 = (targetAddress - (fixupAddress + 6)) + ref.addend(); return; case ripRel32Minus4: *loc32 = ref.addend() - 4; return; case ripRel32Minus4Anon: *loc32 = (targetAddress - (fixupAddress + 8)) + ref.addend(); return; case delta32: *loc32 = ref.addend() + inAtomAddress - fixupAddress; return; case delta32Anon: // The value we write here should be the the delta to the target // after taking in to account the difference from the fixup back to the // last defined label // ie, if we have: // _base: ... // Lfixup: .quad Ltarget - . // ... // Ltarget: // // Then we want to encode the value (Ltarget + addend) - (LFixup - _base) *loc32 = (targetAddress + ref.addend()) - (fixupAddress - inAtomAddress); return; case delta64: *loc64 = ref.addend() + inAtomAddress - fixupAddress; return; case delta64Anon: // The value we write here should be the the delta to the target // after taking in to account the difference from the fixup back to the // last defined label // ie, if we have: // _base: ... // Lfixup: .quad Ltarget - . // ... // Ltarget: // // Then we want to encode the value (Ltarget + addend) - (LFixup - _base) *loc64 = (targetAddress + ref.addend()) - (fixupAddress - inAtomAddress); return; case negDelta64: *loc64 = ref.addend() + fixupAddress - inAtomAddress; return; case negDelta32: *loc32 = ref.addend() + fixupAddress - inAtomAddress; return; case ripRel32GotLoadNowLea: llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run"); return; case lazyPointer: case lazyImmediateLocation: llvm_unreachable("lazy reference kind implies Stubs pass was run"); return; case imageOffset: case imageOffsetGot: case unwindInfoToEhFrame: llvm_unreachable("fixup implies __unwind_info"); return; case unwindFDEToFunction: // Do nothing for now return; case invalid: // Fall into llvm_unreachable(). break; } llvm_unreachable("unknown x86_64 Reference Kind"); } void ArchHandler_x86_64::appendSectionRelocations( const DefinedAtom &atom, uint64_t atomSectionOffset, const Reference &ref, FindSymbolIndexForAtom symbolIndexForAtom, FindSectionIndexForAtom sectionIndexForAtom, FindAddressForAtom addressForAtom, normalized::Relocations &relocs) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return; assert(ref.kindArch() == Reference::KindArch::x86_64); uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom(); switch (static_cast(ref.kindValue())) { case branch32: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_BRANCH | rPcRel | rExtern | rLength4); return; case ripRel32: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_SIGNED | rPcRel | rExtern | rLength4 ); return; case ripRel32Anon: appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, X86_64_RELOC_SIGNED | rPcRel | rLength4 ); return; case ripRel32Got: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_GOT | rPcRel | rExtern | rLength4 ); return; case ripRel32GotLoad: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_GOT_LOAD | rPcRel | rExtern | rLength4 ); return; case ripRel32Tlv: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_TLV | rPcRel | rExtern | rLength4 ); return; case tlvInitSectionOffset: case pointer64: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_UNSIGNED | rExtern | rLength8); return; case pointer64Anon: appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, X86_64_RELOC_UNSIGNED | rLength8); return; case ripRel32Minus1: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_SIGNED_1 | rPcRel | rExtern | rLength4 ); return; case ripRel32Minus1Anon: appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, X86_64_RELOC_SIGNED_1 | rPcRel | rLength4 ); return; case ripRel32Minus2: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_SIGNED_2 | rPcRel | rExtern | rLength4 ); return; case ripRel32Minus2Anon: appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, X86_64_RELOC_SIGNED_2 | rPcRel | rLength4 ); return; case ripRel32Minus4: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_SIGNED_4 | rPcRel | rExtern | rLength4 ); return; case ripRel32Minus4Anon: appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, X86_64_RELOC_SIGNED_4 | rPcRel | rLength4 ); return; case delta32: appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0, X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 ); appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_UNSIGNED | rExtern | rLength4 ); return; case delta32Anon: appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0, X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 ); appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, X86_64_RELOC_UNSIGNED | rLength4 ); return; case delta64: appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0, X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 ); appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_UNSIGNED | rExtern | rLength8 ); return; case delta64Anon: appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0, X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 ); appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, X86_64_RELOC_UNSIGNED | rLength8 ); return; case unwindFDEToFunction: case unwindInfoToEhFrame: return; case negDelta32: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 ); appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0, X86_64_RELOC_UNSIGNED | rExtern | rLength4 ); return; case negDelta64: appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 ); appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0, X86_64_RELOC_UNSIGNED | rExtern | rLength8 ); return; case ripRel32GotLoadNowLea: llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run"); return; case lazyPointer: case lazyImmediateLocation: llvm_unreachable("lazy reference kind implies Stubs pass was run"); return; case imageOffset: case imageOffsetGot: llvm_unreachable("__unwind_info references should have been resolved"); return; case invalid: // Fall into llvm_unreachable(). break; } llvm_unreachable("unknown x86_64 Reference Kind"); } std::unique_ptr ArchHandler::create_x86_64() { return std::unique_ptr(new ArchHandler_x86_64()); } } // namespace mach_o } // namespace lld Index: head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp =================================================================== --- head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp (revision 326908) +++ head/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp (revision 326909) @@ -1,1600 +1,1657 @@ //===- lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp ------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// \file Converts from in-memory Atoms to in-memory normalized mach-o. /// /// +------------+ /// | normalized | /// +------------+ /// ^ /// | /// | /// +-------+ /// | Atoms | /// +-------+ #include "ArchHandler.h" #include "DebugInfo.h" #include "MachONormalizedFile.h" #include "MachONormalizedFileBinaryUtils.h" #include "lld/Core/Error.h" #include "lld/Core/LLVM.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/BinaryFormat/MachO.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include #include #include using llvm::StringRef; using llvm::isa; using namespace llvm::MachO; using namespace lld::mach_o::normalized; using namespace lld; namespace { struct AtomInfo { const DefinedAtom *atom; uint64_t offsetInSection; }; struct SectionInfo { SectionInfo(StringRef seg, StringRef sect, SectionType type, const MachOLinkingContext &ctxt, uint32_t attr, bool relocsToDefinedCanBeImplicit); StringRef segmentName; StringRef sectionName; SectionType type; uint32_t attributes; uint64_t address; uint64_t size; uint16_t alignment; /// If this is set, the any relocs in this section which point to defined /// addresses can be implicitly generated. This is the case for the /// __eh_frame section where references to the function can be implicit if the /// function is defined. bool relocsToDefinedCanBeImplicit; std::vector atomsAndOffsets; uint32_t normalizedSectionIndex; uint32_t finalSectionIndex; }; SectionInfo::SectionInfo(StringRef sg, StringRef sct, SectionType t, const MachOLinkingContext &ctxt, uint32_t attrs, bool relocsToDefinedCanBeImplicit) : segmentName(sg), sectionName(sct), type(t), attributes(attrs), address(0), size(0), alignment(1), relocsToDefinedCanBeImplicit(relocsToDefinedCanBeImplicit), normalizedSectionIndex(0), finalSectionIndex(0) { uint16_t align = 1; if (ctxt.sectionAligned(segmentName, sectionName, align)) { alignment = align; } } struct SegmentInfo { SegmentInfo(StringRef name); StringRef name; uint64_t address; uint64_t size; uint32_t init_access; uint32_t max_access; std::vector sections; uint32_t normalizedSegmentIndex; }; SegmentInfo::SegmentInfo(StringRef n) : name(n), address(0), size(0), init_access(0), max_access(0), normalizedSegmentIndex(0) { } class Util { public: Util(const MachOLinkingContext &ctxt) : _ctx(ctxt), _archHandler(ctxt.archHandler()), _entryAtom(nullptr), _hasTLVDescriptors(false), _subsectionsViaSymbols(true) {} ~Util(); void processDefinedAtoms(const lld::File &atomFile); void processAtomAttributes(const DefinedAtom *atom); void assignAtomToSection(const DefinedAtom *atom); void organizeSections(); void assignAddressesToSections(const NormalizedFile &file); uint32_t fileFlags(); void copySegmentInfo(NormalizedFile &file); void copySectionInfo(NormalizedFile &file); void updateSectionInfo(NormalizedFile &file); void buildAtomToAddressMap(); llvm::Error synthesizeDebugNotes(NormalizedFile &file); llvm::Error addSymbols(const lld::File &atomFile, NormalizedFile &file); void addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file); void addRebaseAndBindingInfo(const lld::File &, NormalizedFile &file); void addExportInfo(const lld::File &, NormalizedFile &file); void addSectionRelocs(const lld::File &, NormalizedFile &file); void addFunctionStarts(const lld::File &, NormalizedFile &file); void buildDataInCodeArray(const lld::File &, NormalizedFile &file); void addDependentDylibs(const lld::File &, NormalizedFile &file); void copyEntryPointAddress(NormalizedFile &file); void copySectionContent(NormalizedFile &file); bool allSourceFilesHaveMinVersions() const { return _allSourceFilesHaveMinVersions; } uint32_t minVersion() const { return _minVersion; } LoadCommandType minVersionCommandType() const { return _minVersionCommandType; } private: typedef std::map TypeToSection; typedef llvm::DenseMap AtomToAddress; struct DylibInfo { int ordinal; bool hasWeak; bool hasNonWeak; }; typedef llvm::StringMap DylibPathToInfo; SectionInfo *sectionForAtom(const DefinedAtom*); SectionInfo *getRelocatableSection(DefinedAtom::ContentType type); SectionInfo *getFinalSection(DefinedAtom::ContentType type); void appendAtom(SectionInfo *sect, const DefinedAtom *atom); SegmentInfo *segmentForName(StringRef segName); void layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr); void layoutSectionsInTextSegment(size_t, SegmentInfo *, uint64_t &); void copySectionContent(SectionInfo *si, ContentBytes &content); uint16_t descBits(const DefinedAtom* atom); int dylibOrdinal(const SharedLibraryAtom *sa); void segIndexForSection(const SectionInfo *sect, uint8_t &segmentIndex, uint64_t &segmentStartAddr); const Atom *targetOfLazyPointer(const DefinedAtom *lpAtom); const Atom *targetOfStub(const DefinedAtom *stubAtom); llvm::Error getSymbolTableRegion(const DefinedAtom* atom, bool &inGlobalsRegion, SymbolScope &symbolScope); void appendSection(SectionInfo *si, NormalizedFile &file); uint32_t sectionIndexForAtom(const Atom *atom); + void fixLazyReferenceImm(const DefinedAtom *atom, uint32_t offset, + NormalizedFile &file); typedef llvm::DenseMap AtomToIndex; struct AtomAndIndex { const Atom *atom; uint32_t index; SymbolScope scope; }; struct AtomSorter { bool operator()(const AtomAndIndex &left, const AtomAndIndex &right); }; struct SegmentSorter { bool operator()(const SegmentInfo *left, const SegmentInfo *right); static unsigned weight(const SegmentInfo *); }; struct TextSectionSorter { bool operator()(const SectionInfo *left, const SectionInfo *right); static unsigned weight(const SectionInfo *); }; const MachOLinkingContext &_ctx; mach_o::ArchHandler &_archHandler; llvm::BumpPtrAllocator _allocator; std::vector _sectionInfos; std::vector _segmentInfos; TypeToSection _sectionMap; std::vector _customSections; AtomToAddress _atomToAddress; DylibPathToInfo _dylibInfo; const DefinedAtom *_entryAtom; AtomToIndex _atomToSymbolIndex; std::vector _machHeaderAliasAtoms; bool _hasTLVDescriptors; bool _subsectionsViaSymbols; bool _allSourceFilesHaveMinVersions = true; LoadCommandType _minVersionCommandType = (LoadCommandType)0; uint32_t _minVersion = 0; std::vector _stabs; }; Util::~Util() { // The SectionInfo structs are BumpPtr allocated, but atomsAndOffsets needs // to be deleted. for (SectionInfo *si : _sectionInfos) { // clear() destroys vector elements, but does not deallocate. // Instead use swap() to deallocate vector buffer. std::vector empty; si->atomsAndOffsets.swap(empty); } // The SegmentInfo structs are BumpPtr allocated, but sections needs // to be deleted. for (SegmentInfo *sgi : _segmentInfos) { std::vector empty2; sgi->sections.swap(empty2); } } SectionInfo *Util::getRelocatableSection(DefinedAtom::ContentType type) { StringRef segmentName; StringRef sectionName; SectionType sectionType; SectionAttr sectionAttrs; bool relocsToDefinedCanBeImplicit; // Use same table used by when parsing .o files. relocatableSectionInfoForContentType(type, segmentName, sectionName, sectionType, sectionAttrs, relocsToDefinedCanBeImplicit); // If we already have a SectionInfo with this name, re-use it. // This can happen if two ContentType map to the same mach-o section. for (auto sect : _sectionMap) { if (sect.second->sectionName.equals(sectionName) && sect.second->segmentName.equals(segmentName)) { return sect.second; } } // Otherwise allocate new SectionInfo object. auto *sect = new (_allocator) SectionInfo(segmentName, sectionName, sectionType, _ctx, sectionAttrs, relocsToDefinedCanBeImplicit); _sectionInfos.push_back(sect); _sectionMap[type] = sect; return sect; } #define ENTRY(seg, sect, type, atomType) \ {seg, sect, type, DefinedAtom::atomType } struct MachOFinalSectionFromAtomType { StringRef segmentName; StringRef sectionName; SectionType sectionType; DefinedAtom::ContentType atomType; }; const MachOFinalSectionFromAtomType sectsToAtomType[] = { ENTRY("__TEXT", "__text", S_REGULAR, typeCode), ENTRY("__TEXT", "__text", S_REGULAR, typeMachHeader), ENTRY("__TEXT", "__cstring", S_CSTRING_LITERALS, typeCString), ENTRY("__TEXT", "__ustring", S_REGULAR, typeUTF16String), ENTRY("__TEXT", "__const", S_REGULAR, typeConstant), ENTRY("__TEXT", "__const", S_4BYTE_LITERALS, typeLiteral4), ENTRY("__TEXT", "__const", S_8BYTE_LITERALS, typeLiteral8), ENTRY("__TEXT", "__const", S_16BYTE_LITERALS, typeLiteral16), ENTRY("__TEXT", "__stubs", S_SYMBOL_STUBS, typeStub), ENTRY("__TEXT", "__stub_helper", S_REGULAR, typeStubHelper), ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR, typeLSDA), ENTRY("__TEXT", "__eh_frame", S_COALESCED, typeCFI), ENTRY("__TEXT", "__unwind_info", S_REGULAR, typeProcessedUnwindInfo), ENTRY("__DATA", "__data", S_REGULAR, typeData), ENTRY("__DATA", "__const", S_REGULAR, typeConstData), ENTRY("__DATA", "__cfstring", S_REGULAR, typeCFString), ENTRY("__DATA", "__la_symbol_ptr", S_LAZY_SYMBOL_POINTERS, typeLazyPointer), ENTRY("__DATA", "__mod_init_func", S_MOD_INIT_FUNC_POINTERS, typeInitializerPtr), ENTRY("__DATA", "__mod_term_func", S_MOD_TERM_FUNC_POINTERS, typeTerminatorPtr), ENTRY("__DATA", "__got", S_NON_LAZY_SYMBOL_POINTERS, typeGOT), ENTRY("__DATA", "__nl_symbol_ptr", S_NON_LAZY_SYMBOL_POINTERS, typeNonLazyPointer), ENTRY("__DATA", "__thread_vars", S_THREAD_LOCAL_VARIABLES, typeThunkTLV), ENTRY("__DATA", "__thread_data", S_THREAD_LOCAL_REGULAR, typeTLVInitialData), ENTRY("__DATA", "__thread_ptrs", S_THREAD_LOCAL_VARIABLE_POINTERS, typeTLVInitializerPtr), ENTRY("__DATA", "__thread_bss", S_THREAD_LOCAL_ZEROFILL, typeTLVInitialZeroFill), ENTRY("__DATA", "__bss", S_ZEROFILL, typeZeroFill), ENTRY("__DATA", "__interposing", S_INTERPOSING, typeInterposingTuples), }; #undef ENTRY SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) { for (auto &p : sectsToAtomType) { if (p.atomType != atomType) continue; SectionAttr sectionAttrs = 0; switch (atomType) { case DefinedAtom::typeMachHeader: case DefinedAtom::typeCode: case DefinedAtom::typeStub: case DefinedAtom::typeStubHelper: sectionAttrs = S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS; break; case DefinedAtom::typeThunkTLV: _hasTLVDescriptors = true; break; default: break; } // If we already have a SectionInfo with this name, re-use it. // This can happen if two ContentType map to the same mach-o section. for (auto sect : _sectionMap) { if (sect.second->sectionName.equals(p.sectionName) && sect.second->segmentName.equals(p.segmentName)) { return sect.second; } } // Otherwise allocate new SectionInfo object. auto *sect = new (_allocator) SectionInfo( p.segmentName, p.sectionName, p.sectionType, _ctx, sectionAttrs, /* relocsToDefinedCanBeImplicit */ false); _sectionInfos.push_back(sect); _sectionMap[atomType] = sect; return sect; } llvm_unreachable("content type not yet supported"); } SectionInfo *Util::sectionForAtom(const DefinedAtom *atom) { if (atom->sectionChoice() == DefinedAtom::sectionBasedOnContent) { // Section for this atom is derived from content type. DefinedAtom::ContentType type = atom->contentType(); auto pos = _sectionMap.find(type); if ( pos != _sectionMap.end() ) return pos->second; bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT); return rMode ? getRelocatableSection(type) : getFinalSection(type); } else { // This atom needs to be in a custom section. StringRef customName = atom->customSectionName(); // Look to see if we have already allocated the needed custom section. for(SectionInfo *sect : _customSections) { const DefinedAtom *firstAtom = sect->atomsAndOffsets.front().atom; if (firstAtom->customSectionName().equals(customName)) { return sect; } } // Not found, so need to create a new custom section. size_t seperatorIndex = customName.find('/'); assert(seperatorIndex != StringRef::npos); StringRef segName = customName.slice(0, seperatorIndex); StringRef sectName = customName.drop_front(seperatorIndex + 1); auto *sect = new (_allocator) SectionInfo(segName, sectName, S_REGULAR, _ctx, 0, /* relocsToDefinedCanBeImplicit */ false); _customSections.push_back(sect); _sectionInfos.push_back(sect); return sect; } } void Util::appendAtom(SectionInfo *sect, const DefinedAtom *atom) { // Figure out offset for atom in this section given alignment constraints. uint64_t offset = sect->size; DefinedAtom::Alignment atomAlign = atom->alignment(); uint64_t align = atomAlign.value; uint64_t requiredModulus = atomAlign.modulus; uint64_t currentModulus = (offset % align); if ( currentModulus != requiredModulus ) { if ( requiredModulus > currentModulus ) offset += requiredModulus-currentModulus; else offset += align+requiredModulus-currentModulus; } // Record max alignment of any atom in this section. if (align > sect->alignment) sect->alignment = atomAlign.value; // Assign atom to this section with this offset. AtomInfo ai = {atom, offset}; sect->atomsAndOffsets.push_back(ai); // Update section size to include this atom. sect->size = offset + atom->size(); } void Util::processDefinedAtoms(const lld::File &atomFile) { for (const DefinedAtom *atom : atomFile.defined()) { processAtomAttributes(atom); assignAtomToSection(atom); } } void Util::processAtomAttributes(const DefinedAtom *atom) { if (auto *machoFile = dyn_cast(&atom->file())) { // If the file doesn't use subsections via symbols, then make sure we don't // add that flag to the final output file if we have a relocatable file. if (!machoFile->subsectionsViaSymbols()) _subsectionsViaSymbols = false; // All the source files must have min versions for us to output an object // file with a min version. if (auto v = machoFile->minVersion()) _minVersion = std::max(_minVersion, v); else _allSourceFilesHaveMinVersions = false; // If we don't have a platform load command, but one of the source files // does, then take the one from the file. if (!_minVersionCommandType) if (auto v = machoFile->minVersionLoadCommandKind()) _minVersionCommandType = v; } } void Util::assignAtomToSection(const DefinedAtom *atom) { if (atom->contentType() == DefinedAtom::typeMachHeader) { _machHeaderAliasAtoms.push_back(atom); // Assign atom to this section with this offset. AtomInfo ai = {atom, 0}; sectionForAtom(atom)->atomsAndOffsets.push_back(ai); } else if (atom->contentType() == DefinedAtom::typeDSOHandle) _machHeaderAliasAtoms.push_back(atom); else appendAtom(sectionForAtom(atom), atom); } SegmentInfo *Util::segmentForName(StringRef segName) { for (SegmentInfo *si : _segmentInfos) { if ( si->name.equals(segName) ) return si; } auto *info = new (_allocator) SegmentInfo(segName); // Set the initial segment protection. if (segName.equals("__TEXT")) info->init_access = VM_PROT_READ | VM_PROT_EXECUTE; else if (segName.equals("__PAGEZERO")) info->init_access = 0; else if (segName.equals("__LINKEDIT")) info->init_access = VM_PROT_READ; else { // All others default to read-write info->init_access = VM_PROT_READ | VM_PROT_WRITE; } // Set max segment protection // Note, its overkill to use a switch statement here, but makes it so much // easier to use switch coverage to catch new cases. switch (_ctx.os()) { case lld::MachOLinkingContext::OS::unknown: case lld::MachOLinkingContext::OS::macOSX: case lld::MachOLinkingContext::OS::iOS_simulator: if (segName.equals("__PAGEZERO")) { info->max_access = 0; break; } // All others default to all info->max_access = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE; break; case lld::MachOLinkingContext::OS::iOS: // iPhoneOS always uses same protection for max and initial info->max_access = info->init_access; break; } _segmentInfos.push_back(info); return info; } unsigned Util::SegmentSorter::weight(const SegmentInfo *seg) { return llvm::StringSwitch(seg->name) .Case("__PAGEZERO", 1) .Case("__TEXT", 2) .Case("__DATA", 3) .Default(100); } bool Util::SegmentSorter::operator()(const SegmentInfo *left, const SegmentInfo *right) { return (weight(left) < weight(right)); } unsigned Util::TextSectionSorter::weight(const SectionInfo *sect) { return llvm::StringSwitch(sect->sectionName) .Case("__text", 1) .Case("__stubs", 2) .Case("__stub_helper", 3) .Case("__const", 4) .Case("__cstring", 5) .Case("__unwind_info", 98) .Case("__eh_frame", 99) .Default(10); } bool Util::TextSectionSorter::operator()(const SectionInfo *left, const SectionInfo *right) { return (weight(left) < weight(right)); } void Util::organizeSections() { // NOTE!: Keep this in sync with assignAddressesToSections. switch (_ctx.outputMachOType()) { case llvm::MachO::MH_EXECUTE: // Main executables, need a zero-page segment segmentForName("__PAGEZERO"); // Fall into next case. LLVM_FALLTHROUGH; case llvm::MachO::MH_DYLIB: case llvm::MachO::MH_BUNDLE: // All dynamic code needs TEXT segment to hold the load commands. segmentForName("__TEXT"); break; default: break; } segmentForName("__LINKEDIT"); // Group sections into segments. for (SectionInfo *si : _sectionInfos) { SegmentInfo *seg = segmentForName(si->segmentName); seg->sections.push_back(si); } // Sort segments. std::sort(_segmentInfos.begin(), _segmentInfos.end(), SegmentSorter()); // Sort sections within segments. for (SegmentInfo *seg : _segmentInfos) { if (seg->name.equals("__TEXT")) { std::sort(seg->sections.begin(), seg->sections.end(), TextSectionSorter()); } } // Record final section indexes. uint32_t segmentIndex = 0; uint32_t sectionIndex = 1; for (SegmentInfo *seg : _segmentInfos) { seg->normalizedSegmentIndex = segmentIndex++; for (SectionInfo *sect : seg->sections) sect->finalSectionIndex = sectionIndex++; } } void Util::layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr) { seg->address = addr; for (SectionInfo *sect : seg->sections) { sect->address = llvm::alignTo(addr, sect->alignment); addr = sect->address + sect->size; } seg->size = llvm::alignTo(addr - seg->address, _ctx.pageSize()); } // __TEXT segment lays out backwards so padding is at front after load commands. void Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg, uint64_t &addr) { seg->address = addr; // Walks sections starting at end to calculate padding for start. int64_t taddr = 0; for (auto it = seg->sections.rbegin(); it != seg->sections.rend(); ++it) { SectionInfo *sect = *it; taddr -= sect->size; taddr = taddr & (0 - sect->alignment); } int64_t padding = taddr - hlcSize; while (padding < 0) padding += _ctx.pageSize(); // Start assigning section address starting at padded offset. addr += (padding + hlcSize); for (SectionInfo *sect : seg->sections) { sect->address = llvm::alignTo(addr, sect->alignment); addr = sect->address + sect->size; } seg->size = llvm::alignTo(addr - seg->address, _ctx.pageSize()); } void Util::assignAddressesToSections(const NormalizedFile &file) { // NOTE!: Keep this in sync with organizeSections. size_t hlcSize = headerAndLoadCommandsSize(file); uint64_t address = 0; for (SegmentInfo *seg : _segmentInfos) { if (seg->name.equals("__PAGEZERO")) { seg->size = _ctx.pageZeroSize(); address += seg->size; } else if (seg->name.equals("__TEXT")) { // _ctx.baseAddress() == 0 implies it was either unspecified or // pageZeroSize is also 0. In either case resetting address is safe. address = _ctx.baseAddress() ? _ctx.baseAddress() : address; layoutSectionsInTextSegment(hlcSize, seg, address); } else layoutSectionsInSegment(seg, address); address = llvm::alignTo(address, _ctx.pageSize()); } DEBUG_WITH_TYPE("WriterMachO-norm", llvm::dbgs() << "assignAddressesToSections()\n"; for (SegmentInfo *sgi : _segmentInfos) { llvm::dbgs() << " address=" << llvm::format("0x%08llX", sgi->address) << ", size=" << llvm::format("0x%08llX", sgi->size) << ", segment-name='" << sgi->name << "'\n"; for (SectionInfo *si : sgi->sections) { llvm::dbgs()<< " addr=" << llvm::format("0x%08llX", si->address) << ", size=" << llvm::format("0x%08llX", si->size) << ", section-name='" << si->sectionName << "\n"; } } ); } void Util::copySegmentInfo(NormalizedFile &file) { for (SegmentInfo *sgi : _segmentInfos) { Segment seg; seg.name = sgi->name; seg.address = sgi->address; seg.size = sgi->size; seg.init_access = sgi->init_access; seg.max_access = sgi->max_access; file.segments.push_back(seg); } } void Util::appendSection(SectionInfo *si, NormalizedFile &file) { // Add new empty section to end of file.sections. Section temp; file.sections.push_back(std::move(temp)); Section* normSect = &file.sections.back(); // Copy fields to normalized section. normSect->segmentName = si->segmentName; normSect->sectionName = si->sectionName; normSect->type = si->type; normSect->attributes = si->attributes; normSect->address = si->address; normSect->alignment = si->alignment; // Record where normalized section is. si->normalizedSectionIndex = file.sections.size()-1; } void Util::copySectionContent(NormalizedFile &file) { const bool r = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT); // Utility function for ArchHandler to find address of atom in output file. auto addrForAtom = [&] (const Atom &atom) -> uint64_t { auto pos = _atomToAddress.find(&atom); assert(pos != _atomToAddress.end()); return pos->second; }; auto sectionAddrForAtom = [&] (const Atom &atom) -> uint64_t { for (const SectionInfo *sectInfo : _sectionInfos) for (const AtomInfo &atomInfo : sectInfo->atomsAndOffsets) if (atomInfo.atom == &atom) return sectInfo->address; llvm_unreachable("atom not assigned to section"); }; for (SectionInfo *si : _sectionInfos) { Section *normSect = &file.sections[si->normalizedSectionIndex]; if (isZeroFillSection(si->type)) { const uint8_t *empty = nullptr; normSect->content = llvm::makeArrayRef(empty, si->size); continue; } // Copy content from atoms to content buffer for section. llvm::MutableArrayRef sectionContent; if (si->size) { uint8_t *sectContent = file.ownedAllocations.Allocate(si->size); sectionContent = llvm::MutableArrayRef(sectContent, si->size); normSect->content = sectionContent; } for (AtomInfo &ai : si->atomsAndOffsets) { if (!ai.atom->size()) { assert(ai.atom->begin() == ai.atom->end() && "Cannot have references without content"); continue; } auto atomContent = sectionContent.slice(ai.offsetInSection, ai.atom->size()); _archHandler.generateAtomContent(*ai.atom, r, addrForAtom, sectionAddrForAtom, _ctx.baseAddress(), atomContent); } } } void Util::copySectionInfo(NormalizedFile &file) { file.sections.reserve(_sectionInfos.size()); // Write sections grouped by segment. for (SegmentInfo *sgi : _segmentInfos) { for (SectionInfo *si : sgi->sections) { appendSection(si, file); } } } void Util::updateSectionInfo(NormalizedFile &file) { file.sections.reserve(_sectionInfos.size()); // sections grouped by segment. for (SegmentInfo *sgi : _segmentInfos) { Segment *normSeg = &file.segments[sgi->normalizedSegmentIndex]; normSeg->address = sgi->address; normSeg->size = sgi->size; for (SectionInfo *si : sgi->sections) { Section *normSect = &file.sections[si->normalizedSectionIndex]; normSect->address = si->address; } } } void Util::copyEntryPointAddress(NormalizedFile &nFile) { if (!_entryAtom) { nFile.entryAddress = 0; return; } if (_ctx.outputTypeHasEntry()) { if (_archHandler.isThumbFunction(*_entryAtom)) nFile.entryAddress = (_atomToAddress[_entryAtom] | 1); else nFile.entryAddress = _atomToAddress[_entryAtom]; } } void Util::buildAtomToAddressMap() { DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() << "assign atom addresses:\n"); const bool lookForEntry = _ctx.outputTypeHasEntry(); for (SectionInfo *sect : _sectionInfos) { for (const AtomInfo &info : sect->atomsAndOffsets) { _atomToAddress[info.atom] = sect->address + info.offsetInSection; if (lookForEntry && (info.atom->contentType() == DefinedAtom::typeCode) && (info.atom->size() != 0) && info.atom->name() == _ctx.entrySymbolName()) { _entryAtom = info.atom; } DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() << " address=" << llvm::format("0x%016X", _atomToAddress[info.atom]) << llvm::format(" 0x%09lX", info.atom) << ", file=#" << info.atom->file().ordinal() << ", atom=#" << info.atom->ordinal() << ", name=" << info.atom->name() << ", type=" << info.atom->contentType() << "\n"); } } DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() << "assign header alias atom addresses:\n"); for (const Atom *atom : _machHeaderAliasAtoms) { _atomToAddress[atom] = _ctx.baseAddress(); #ifndef NDEBUG if (auto *definedAtom = dyn_cast(atom)) { DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() << " address=" << llvm::format("0x%016X", _atomToAddress[atom]) << llvm::format(" 0x%09lX", atom) << ", file=#" << definedAtom->file().ordinal() << ", atom=#" << definedAtom->ordinal() << ", name=" << definedAtom->name() << ", type=" << definedAtom->contentType() << "\n"); } else { DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() << " address=" << llvm::format("0x%016X", _atomToAddress[atom]) << " atom=" << atom << " name=" << atom->name() << "\n"); } #endif } } llvm::Error Util::synthesizeDebugNotes(NormalizedFile &file) { // Bail out early if we don't need to generate a debug map. if (_ctx.debugInfoMode() == MachOLinkingContext::DebugInfoMode::noDebugMap) return llvm::Error::success(); std::vector atomsNeedingDebugNotes; std::set filesWithStabs; bool objFileHasDwarf = false; const File *objFile = nullptr; for (SectionInfo *sect : _sectionInfos) { for (const AtomInfo &info : sect->atomsAndOffsets) { if (const DefinedAtom *atom = dyn_cast(info.atom)) { // FIXME: No stabs/debug-notes for symbols that wouldn't be in the // symbol table. // FIXME: No stabs/debug-notes for kernel dtrace probes. if (atom->contentType() == DefinedAtom::typeCFI || atom->contentType() == DefinedAtom::typeCString) continue; // Whenever we encounter a new file, update the 'objfileHasDwarf' flag. if (&info.atom->file() != objFile) { objFileHasDwarf = false; if (const mach_o::MachOFile *atomFile = dyn_cast(&info.atom->file())) { if (atomFile->debugInfo()) { if (isa(atomFile->debugInfo())) objFileHasDwarf = true; else if (isa(atomFile->debugInfo())) filesWithStabs.insert(atomFile); } } } // If this atom is from a file that needs dwarf, add it to the list. if (objFileHasDwarf) atomsNeedingDebugNotes.push_back(info.atom); } } } // Sort atoms needing debug notes by file ordinal, then atom ordinal. std::sort(atomsNeedingDebugNotes.begin(), atomsNeedingDebugNotes.end(), [](const DefinedAtom *lhs, const DefinedAtom *rhs) { if (lhs->file().ordinal() != rhs->file().ordinal()) return (lhs->file().ordinal() < rhs->file().ordinal()); return (lhs->ordinal() < rhs->ordinal()); }); // FIXME: Handle : Add -add_ast_path option to \ // linker which add N_AST stab entry to output // See OutputFile::synthesizeDebugNotes in ObjectFile.cpp in ld64. StringRef oldFileName = ""; StringRef oldDirPath = ""; bool wroteStartSO = false; std::unordered_set seenFiles; for (const DefinedAtom *atom : atomsNeedingDebugNotes) { const auto &atomFile = cast(atom->file()); assert(dyn_cast_or_null(atomFile.debugInfo()) && "file for atom needing debug notes does not contain dwarf"); auto &dwarf = cast(*atomFile.debugInfo()); auto &tu = dwarf.translationUnitSource(); StringRef newFileName = tu.name; StringRef newDirPath = tu.path; // Add an SO whenever the TU source file changes. if (newFileName != oldFileName || newDirPath != oldDirPath) { // Translation unit change, emit ending SO if (oldFileName != "") _stabs.push_back(mach_o::Stab(nullptr, N_SO, 1, 0, 0, "")); oldFileName = newFileName; oldDirPath = newDirPath; // If newDirPath doesn't end with a '/' we need to add one: if (newDirPath.back() != '/') { char *p = file.ownedAllocations.Allocate(newDirPath.size() + 2); memcpy(p, newDirPath.data(), newDirPath.size()); p[newDirPath.size()] = '/'; p[newDirPath.size() + 1] = '\0'; newDirPath = p; } // New translation unit, emit start SOs: _stabs.push_back(mach_o::Stab(nullptr, N_SO, 0, 0, 0, newDirPath)); _stabs.push_back(mach_o::Stab(nullptr, N_SO, 0, 0, 0, newFileName)); // Synthesize OSO for start of file. char *fullPath = nullptr; { SmallString<1024> pathBuf(atomFile.path()); if (auto EC = llvm::sys::fs::make_absolute(pathBuf)) return llvm::errorCodeToError(EC); fullPath = file.ownedAllocations.Allocate(pathBuf.size() + 1); memcpy(fullPath, pathBuf.c_str(), pathBuf.size() + 1); } // Get mod time. uint32_t modTime = 0; llvm::sys::fs::file_status stat; if (!llvm::sys::fs::status(fullPath, stat)) if (llvm::sys::fs::exists(stat)) modTime = llvm::sys::toTimeT(stat.getLastModificationTime()); _stabs.push_back(mach_o::Stab(nullptr, N_OSO, _ctx.getCPUSubType(), 1, modTime, fullPath)); // linker should put cpusubtype in n_sect field // of nlist entry for N_OSO debug note entries. wroteStartSO = true; } if (atom->contentType() == DefinedAtom::typeCode) { // Synthesize BNSYM and start FUN stabs. _stabs.push_back(mach_o::Stab(atom, N_BNSYM, 1, 0, 0, "")); _stabs.push_back(mach_o::Stab(atom, N_FUN, 1, 0, 0, atom->name())); // Synthesize any SOL stabs needed // FIXME: add SOL stabs. _stabs.push_back(mach_o::Stab(nullptr, N_FUN, 0, 0, atom->rawContent().size(), "")); _stabs.push_back(mach_o::Stab(nullptr, N_ENSYM, 1, 0, atom->rawContent().size(), "")); } else { if (atom->scope() == Atom::scopeTranslationUnit) _stabs.push_back(mach_o::Stab(atom, N_STSYM, 1, 0, 0, atom->name())); else _stabs.push_back(mach_o::Stab(nullptr, N_GSYM, 1, 0, 0, atom->name())); } } // Emit ending SO if necessary. if (wroteStartSO) _stabs.push_back(mach_o::Stab(nullptr, N_SO, 1, 0, 0, "")); // Copy any stabs from .o file. for (const auto *objFile : filesWithStabs) { const auto &stabsList = cast(objFile->debugInfo())->stabs(); for (auto &stab : stabsList) { // FIXME: Drop stabs whose atoms have been dead-stripped. _stabs.push_back(stab); } } return llvm::Error::success(); } uint16_t Util::descBits(const DefinedAtom* atom) { uint16_t desc = 0; switch (atom->merge()) { case lld::DefinedAtom::mergeNo: case lld::DefinedAtom::mergeAsTentative: break; case lld::DefinedAtom::mergeAsWeak: case lld::DefinedAtom::mergeAsWeakAndAddressUsed: desc |= N_WEAK_DEF; break; case lld::DefinedAtom::mergeSameNameAndSize: case lld::DefinedAtom::mergeByLargestSection: case lld::DefinedAtom::mergeByContent: llvm_unreachable("Unsupported DefinedAtom::merge()"); break; } if (atom->contentType() == lld::DefinedAtom::typeResolver) desc |= N_SYMBOL_RESOLVER; if (atom->contentType() == lld::DefinedAtom::typeMachHeader) desc |= REFERENCED_DYNAMICALLY; if (_archHandler.isThumbFunction(*atom)) desc |= N_ARM_THUMB_DEF; if (atom->deadStrip() == DefinedAtom::deadStripNever && _ctx.outputMachOType() == llvm::MachO::MH_OBJECT) { if ((atom->contentType() != DefinedAtom::typeInitializerPtr) && (atom->contentType() != DefinedAtom::typeTerminatorPtr)) desc |= N_NO_DEAD_STRIP; } return desc; } bool Util::AtomSorter::operator()(const AtomAndIndex &left, const AtomAndIndex &right) { return (left.atom->name().compare(right.atom->name()) < 0); } llvm::Error Util::getSymbolTableRegion(const DefinedAtom* atom, bool &inGlobalsRegion, SymbolScope &scope) { bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT); switch (atom->scope()) { case Atom::scopeTranslationUnit: scope = 0; inGlobalsRegion = false; return llvm::Error::success(); case Atom::scopeLinkageUnit: if ((_ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) && _ctx.exportSymbolNamed(atom->name())) { return llvm::make_error( Twine("cannot export hidden symbol ") + atom->name()); } if (rMode) { if (_ctx.keepPrivateExterns()) { // -keep_private_externs means keep in globals region as N_PEXT. scope = N_PEXT | N_EXT; inGlobalsRegion = true; return llvm::Error::success(); } } // scopeLinkageUnit symbols are no longer global once linked. scope = N_PEXT; inGlobalsRegion = false; return llvm::Error::success(); case Atom::scopeGlobal: if (_ctx.exportRestrictMode()) { if (_ctx.exportSymbolNamed(atom->name())) { scope = N_EXT; inGlobalsRegion = true; return llvm::Error::success(); } else { scope = N_PEXT; inGlobalsRegion = false; return llvm::Error::success(); } } else { scope = N_EXT; inGlobalsRegion = true; return llvm::Error::success(); } break; } llvm_unreachable("atom->scope() unknown enum value"); } llvm::Error Util::addSymbols(const lld::File &atomFile, NormalizedFile &file) { bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT); // Mach-O symbol table has four regions: stabs, locals, globals, undefs. // Add all stabs. for (auto &stab : _stabs) { Symbol sym; sym.type = static_cast(stab.type); sym.scope = 0; sym.sect = stab.other; sym.desc = stab.desc; if (stab.atom) sym.value = _atomToAddress[stab.atom]; else sym.value = stab.value; sym.name = stab.str; file.stabsSymbols.push_back(sym); } // Add all local (non-global) symbols in address order std::vector globals; globals.reserve(512); for (SectionInfo *sect : _sectionInfos) { for (const AtomInfo &info : sect->atomsAndOffsets) { const DefinedAtom *atom = info.atom; if (!atom->name().empty()) { SymbolScope symbolScope; bool inGlobalsRegion; if (auto ec = getSymbolTableRegion(atom, inGlobalsRegion, symbolScope)){ return ec; } if (inGlobalsRegion) { AtomAndIndex ai = { atom, sect->finalSectionIndex, symbolScope }; globals.push_back(ai); } else { Symbol sym; sym.name = atom->name(); sym.type = N_SECT; sym.scope = symbolScope; sym.sect = sect->finalSectionIndex; sym.desc = descBits(atom); sym.value = _atomToAddress[atom]; _atomToSymbolIndex[atom] = file.localSymbols.size(); file.localSymbols.push_back(sym); } } else if (rMode && _archHandler.needsLocalSymbolInRelocatableFile(atom)){ // Create 'Lxxx' labels for anonymous atoms if archHandler says so. static unsigned tempNum = 1; char tmpName[16]; sprintf(tmpName, "L%04u", tempNum++); StringRef tempRef(tmpName); Symbol sym; sym.name = tempRef.copy(file.ownedAllocations); sym.type = N_SECT; sym.scope = 0; sym.sect = sect->finalSectionIndex; sym.desc = 0; sym.value = _atomToAddress[atom]; _atomToSymbolIndex[atom] = file.localSymbols.size(); file.localSymbols.push_back(sym); } } } // Sort global symbol alphabetically, then add to symbol table. std::sort(globals.begin(), globals.end(), AtomSorter()); const uint32_t globalStartIndex = file.localSymbols.size(); for (AtomAndIndex &ai : globals) { Symbol sym; sym.name = ai.atom->name(); sym.type = N_SECT; sym.scope = ai.scope; sym.sect = ai.index; sym.desc = descBits(static_cast(ai.atom)); sym.value = _atomToAddress[ai.atom]; _atomToSymbolIndex[ai.atom] = globalStartIndex + file.globalSymbols.size(); file.globalSymbols.push_back(sym); } // Sort undefined symbol alphabetically, then add to symbol table. std::vector undefs; undefs.reserve(128); for (const UndefinedAtom *atom : atomFile.undefined()) { AtomAndIndex ai = { atom, 0, N_EXT }; undefs.push_back(ai); } for (const SharedLibraryAtom *atom : atomFile.sharedLibrary()) { AtomAndIndex ai = { atom, 0, N_EXT }; undefs.push_back(ai); } std::sort(undefs.begin(), undefs.end(), AtomSorter()); const uint32_t start = file.globalSymbols.size() + file.localSymbols.size(); for (AtomAndIndex &ai : undefs) { Symbol sym; uint16_t desc = 0; if (!rMode) { uint8_t ordinal = 0; if (!_ctx.useFlatNamespace()) ordinal = dylibOrdinal(dyn_cast(ai.atom)); llvm::MachO::SET_LIBRARY_ORDINAL(desc, ordinal); } sym.name = ai.atom->name(); sym.type = N_UNDF; sym.scope = ai.scope; sym.sect = 0; sym.desc = desc; sym.value = 0; _atomToSymbolIndex[ai.atom] = file.undefinedSymbols.size() + start; file.undefinedSymbols.push_back(sym); } return llvm::Error::success(); } const Atom *Util::targetOfLazyPointer(const DefinedAtom *lpAtom) { for (const Reference *ref : *lpAtom) { if (_archHandler.isLazyPointer(*ref)) { return ref->target(); } } return nullptr; } const Atom *Util::targetOfStub(const DefinedAtom *stubAtom) { for (const Reference *ref : *stubAtom) { if (const Atom *ta = ref->target()) { if (const DefinedAtom *lpAtom = dyn_cast(ta)) { const Atom *target = targetOfLazyPointer(lpAtom); if (target) return target; } } } return nullptr; } void Util::addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file) { for (SectionInfo *si : _sectionInfos) { Section &normSect = file.sections[si->normalizedSectionIndex]; switch (si->type) { case llvm::MachO::S_NON_LAZY_SYMBOL_POINTERS: for (const AtomInfo &info : si->atomsAndOffsets) { bool foundTarget = false; for (const Reference *ref : *info.atom) { const Atom *target = ref->target(); if (target) { if (isa(target)) { uint32_t index = _atomToSymbolIndex[target]; normSect.indirectSymbols.push_back(index); foundTarget = true; } else { normSect.indirectSymbols.push_back( llvm::MachO::INDIRECT_SYMBOL_LOCAL); } } } if (!foundTarget) { normSect.indirectSymbols.push_back( llvm::MachO::INDIRECT_SYMBOL_ABS); } } break; case llvm::MachO::S_LAZY_SYMBOL_POINTERS: for (const AtomInfo &info : si->atomsAndOffsets) { const Atom *target = targetOfLazyPointer(info.atom); if (target) { uint32_t index = _atomToSymbolIndex[target]; normSect.indirectSymbols.push_back(index); } } break; case llvm::MachO::S_SYMBOL_STUBS: for (const AtomInfo &info : si->atomsAndOffsets) { const Atom *target = targetOfStub(info.atom); if (target) { uint32_t index = _atomToSymbolIndex[target]; normSect.indirectSymbols.push_back(index); } } break; default: break; } } } void Util::addDependentDylibs(const lld::File &atomFile, NormalizedFile &nFile) { // Scan all imported symbols and build up list of dylibs they are from. int ordinal = 1; for (const auto *dylib : _ctx.allDylibs()) { DylibPathToInfo::iterator pos = _dylibInfo.find(dylib->installName()); if (pos == _dylibInfo.end()) { DylibInfo info; bool flatNamespaceAtom = dylib == _ctx.flatNamespaceFile(); // If we're in -flat_namespace mode (or this atom came from the flat // namespace file under -undefined dynamic_lookup) then use the flat // lookup ordinal. if (flatNamespaceAtom || _ctx.useFlatNamespace()) info.ordinal = BIND_SPECIAL_DYLIB_FLAT_LOOKUP; else info.ordinal = ordinal++; info.hasWeak = false; info.hasNonWeak = !info.hasWeak; _dylibInfo[dylib->installName()] = info; // Unless this was a flat_namespace atom, record the source dylib. if (!flatNamespaceAtom) { DependentDylib depInfo; depInfo.path = dylib->installName(); depInfo.kind = llvm::MachO::LC_LOAD_DYLIB; depInfo.currentVersion = _ctx.dylibCurrentVersion(dylib->path()); depInfo.compatVersion = _ctx.dylibCompatVersion(dylib->path()); nFile.dependentDylibs.push_back(depInfo); } } else { pos->second.hasWeak = false; pos->second.hasNonWeak = !pos->second.hasWeak; } } // Automatically weak link dylib in which all symbols are weak (canBeNull). for (DependentDylib &dep : nFile.dependentDylibs) { DylibInfo &info = _dylibInfo[dep.path]; if (info.hasWeak && !info.hasNonWeak) dep.kind = llvm::MachO::LC_LOAD_WEAK_DYLIB; else if (_ctx.isUpwardDylib(dep.path)) dep.kind = llvm::MachO::LC_LOAD_UPWARD_DYLIB; } } int Util::dylibOrdinal(const SharedLibraryAtom *sa) { return _dylibInfo[sa->loadName()].ordinal; } void Util::segIndexForSection(const SectionInfo *sect, uint8_t &segmentIndex, uint64_t &segmentStartAddr) { segmentIndex = 0; for (const SegmentInfo *seg : _segmentInfos) { if ((seg->address <= sect->address) && (seg->address+seg->size >= sect->address+sect->size)) { segmentStartAddr = seg->address; return; } ++segmentIndex; } llvm_unreachable("section not in any segment"); } uint32_t Util::sectionIndexForAtom(const Atom *atom) { uint64_t address = _atomToAddress[atom]; for (const SectionInfo *si : _sectionInfos) { if ((si->address <= address) && (address < si->address+si->size)) return si->finalSectionIndex; } llvm_unreachable("atom not in any section"); } void Util::addSectionRelocs(const lld::File &, NormalizedFile &file) { if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT) return; // Utility function for ArchHandler to find symbol index for an atom. auto symIndexForAtom = [&] (const Atom &atom) -> uint32_t { auto pos = _atomToSymbolIndex.find(&atom); assert(pos != _atomToSymbolIndex.end()); return pos->second; }; // Utility function for ArchHandler to find section index for an atom. auto sectIndexForAtom = [&] (const Atom &atom) -> uint32_t { return sectionIndexForAtom(&atom); }; // Utility function for ArchHandler to find address of atom in output file. auto addressForAtom = [&] (const Atom &atom) -> uint64_t { auto pos = _atomToAddress.find(&atom); assert(pos != _atomToAddress.end()); return pos->second; }; for (SectionInfo *si : _sectionInfos) { Section &normSect = file.sections[si->normalizedSectionIndex]; for (const AtomInfo &info : si->atomsAndOffsets) { const DefinedAtom *atom = info.atom; for (const Reference *ref : *atom) { // Skip emitting relocs for sections which are always able to be // implicitly regenerated and where the relocation targets an address // which is defined. if (si->relocsToDefinedCanBeImplicit && isa(ref->target())) continue; _archHandler.appendSectionRelocations(*atom, info.offsetInSection, *ref, symIndexForAtom, sectIndexForAtom, addressForAtom, normSect.relocations); } } } } void Util::addFunctionStarts(const lld::File &, NormalizedFile &file) { if (!_ctx.generateFunctionStartsLoadCommand()) return; file.functionStarts.reserve(8192); // Delta compress function starts, starting with the mach header symbol. const uint64_t badAddress = ~0ULL; uint64_t addr = badAddress; for (SectionInfo *si : _sectionInfos) { for (const AtomInfo &info : si->atomsAndOffsets) { auto type = info.atom->contentType(); if (type == DefinedAtom::typeMachHeader) { addr = _atomToAddress[info.atom]; continue; } if (type != DefinedAtom::typeCode) continue; assert(addr != badAddress && "Missing mach header symbol"); // Skip atoms which have 0 size. This is so that LC_FUNCTION_STARTS // can't spill in to the next section. if (!info.atom->size()) continue; uint64_t nextAddr = _atomToAddress[info.atom]; if (_archHandler.isThumbFunction(*info.atom)) nextAddr |= 1; uint64_t delta = nextAddr - addr; if (delta) { ByteBuffer buffer; buffer.append_uleb128(delta); file.functionStarts.insert(file.functionStarts.end(), buffer.bytes(), buffer.bytes() + buffer.size()); } addr = nextAddr; } } // Null terminate, and pad to pointer size for this arch. file.functionStarts.push_back(0); auto size = file.functionStarts.size(); for (unsigned i = size, e = llvm::alignTo(size, _ctx.is64Bit() ? 8 : 4); i != e; ++i) file.functionStarts.push_back(0); } void Util::buildDataInCodeArray(const lld::File &, NormalizedFile &file) { if (!_ctx.generateDataInCodeLoadCommand()) return; for (SectionInfo *si : _sectionInfos) { for (const AtomInfo &info : si->atomsAndOffsets) { // Atoms that contain data-in-code have "transition" references // which mark a point where the embedded data starts of ends. // This needs to be converted to the mach-o format which is an array // of data-in-code ranges. uint32_t startOffset = 0; DataRegionType mode = DataRegionType(0); for (const Reference *ref : *info.atom) { if (ref->kindNamespace() != Reference::KindNamespace::mach_o) continue; if (_archHandler.isDataInCodeTransition(ref->kindValue())) { DataRegionType nextMode = (DataRegionType)ref->addend(); if (mode != nextMode) { if (mode != 0) { // Found end data range, so make range entry. DataInCode entry; entry.offset = si->address + info.offsetInSection + startOffset; entry.length = ref->offsetInAtom() - startOffset; entry.kind = mode; file.dataInCode.push_back(entry); } } mode = nextMode; startOffset = ref->offsetInAtom(); } } if (mode != 0) { // Function ends with data (no end transition). DataInCode entry; entry.offset = si->address + info.offsetInSection + startOffset; entry.length = info.atom->size() - startOffset; entry.kind = mode; file.dataInCode.push_back(entry); } } } } void Util::addRebaseAndBindingInfo(const lld::File &atomFile, NormalizedFile &nFile) { if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT) return; uint8_t segmentIndex; uint64_t segmentStartAddr; + uint32_t offsetInBindInfo = 0; + for (SectionInfo *sect : _sectionInfos) { segIndexForSection(sect, segmentIndex, segmentStartAddr); for (const AtomInfo &info : sect->atomsAndOffsets) { const DefinedAtom *atom = info.atom; for (const Reference *ref : *atom) { uint64_t segmentOffset = _atomToAddress[atom] + ref->offsetInAtom() - segmentStartAddr; const Atom* targ = ref->target(); if (_archHandler.isPointer(*ref)) { // A pointer to a DefinedAtom requires rebasing. if (isa(targ)) { RebaseLocation rebase; rebase.segIndex = segmentIndex; rebase.segOffset = segmentOffset; rebase.kind = llvm::MachO::REBASE_TYPE_POINTER; nFile.rebasingInfo.push_back(rebase); } // A pointer to an SharedLibraryAtom requires binding. if (const SharedLibraryAtom *sa = dyn_cast(targ)) { BindLocation bind; bind.segIndex = segmentIndex; bind.segOffset = segmentOffset; bind.kind = llvm::MachO::BIND_TYPE_POINTER; bind.canBeNull = sa->canBeNullAtRuntime(); bind.ordinal = dylibOrdinal(sa); bind.symbolName = targ->name(); bind.addend = ref->addend(); nFile.bindingInfo.push_back(bind); } } else if (_archHandler.isLazyPointer(*ref)) { BindLocation bind; if (const SharedLibraryAtom *sa = dyn_cast(targ)) { bind.ordinal = dylibOrdinal(sa); } else { bind.ordinal = llvm::MachO::BIND_SPECIAL_DYLIB_SELF; } bind.segIndex = segmentIndex; bind.segOffset = segmentOffset; bind.kind = llvm::MachO::BIND_TYPE_POINTER; bind.canBeNull = false; //sa->canBeNullAtRuntime(); bind.symbolName = targ->name(); bind.addend = ref->addend(); nFile.lazyBindingInfo.push_back(bind); + + // Now that we know the segmentOffset and the ordinal attribute, + // we can fix the helper's code + + fixLazyReferenceImm(atom, offsetInBindInfo, nFile); + + // 5 bytes for opcodes + variable sizes (target name + \0 and offset + // encode's size) + offsetInBindInfo += + 6 + targ->name().size() + llvm::getULEB128Size(bind.segOffset); + if (bind.ordinal > BIND_IMMEDIATE_MASK) + offsetInBindInfo += llvm::getULEB128Size(bind.ordinal); + } + } + } + } +} + +void Util::fixLazyReferenceImm(const DefinedAtom *atom, uint32_t offset, + NormalizedFile &file) { + for (const auto &ref : *atom) { + const DefinedAtom *da = dyn_cast(ref->target()); + if (da == nullptr) + return; + + const Reference *helperRef = nullptr; + for (const Reference *hr : *da) { + if (hr->kindValue() == _archHandler.lazyImmediateLocationKind()) { + helperRef = hr; + break; + } + } + if (helperRef == nullptr) + continue; + + // TODO: maybe get the fixed atom content from _archHandler ? + for (SectionInfo *sectInfo : _sectionInfos) { + for (const AtomInfo &atomInfo : sectInfo->atomsAndOffsets) { + if (atomInfo.atom == helperRef->target()) { + auto sectionContent = + file.sections[sectInfo->normalizedSectionIndex].content; + uint8_t *rawb = + file.ownedAllocations.Allocate(sectionContent.size()); + llvm::MutableArrayRef newContent{rawb, + sectionContent.size()}; + std::copy(sectionContent.begin(), sectionContent.end(), + newContent.begin()); + llvm::support::ulittle32_t *loc = + reinterpret_cast( + &newContent[atomInfo.offsetInSection + + helperRef->offsetInAtom()]); + *loc = offset; + file.sections[sectInfo->normalizedSectionIndex].content = newContent; } } } } } void Util::addExportInfo(const lld::File &atomFile, NormalizedFile &nFile) { if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT) return; for (SectionInfo *sect : _sectionInfos) { for (const AtomInfo &info : sect->atomsAndOffsets) { const DefinedAtom *atom = info.atom; if (atom->scope() != Atom::scopeGlobal) continue; if (_ctx.exportRestrictMode()) { if (!_ctx.exportSymbolNamed(atom->name())) continue; } Export exprt; exprt.name = atom->name(); exprt.offset = _atomToAddress[atom] - _ctx.baseAddress(); exprt.kind = EXPORT_SYMBOL_FLAGS_KIND_REGULAR; if (atom->merge() == DefinedAtom::mergeAsWeak) exprt.flags = EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION; else exprt.flags = 0; exprt.otherOffset = 0; exprt.otherName = StringRef(); nFile.exportInfo.push_back(exprt); } } } uint32_t Util::fileFlags() { // FIXME: these need to determined at runtime. if (_ctx.outputMachOType() == MH_OBJECT) { return _subsectionsViaSymbols ? MH_SUBSECTIONS_VIA_SYMBOLS : 0; } else { uint32_t flags = MH_DYLDLINK; if (!_ctx.useFlatNamespace()) flags |= MH_TWOLEVEL | MH_NOUNDEFS; if ((_ctx.outputMachOType() == MH_EXECUTE) && _ctx.PIE()) flags |= MH_PIE; if (_hasTLVDescriptors) flags |= (MH_PIE | MH_HAS_TLV_DESCRIPTORS); return flags; } } } // end anonymous namespace namespace lld { namespace mach_o { namespace normalized { /// Convert a set of Atoms into a normalized mach-o file. llvm::Expected> normalizedFromAtoms(const lld::File &atomFile, const MachOLinkingContext &context) { // The util object buffers info until the normalized file can be made. Util util(context); util.processDefinedAtoms(atomFile); util.organizeSections(); std::unique_ptr f(new NormalizedFile()); NormalizedFile &normFile = *f.get(); normFile.arch = context.arch(); normFile.fileType = context.outputMachOType(); normFile.flags = util.fileFlags(); normFile.stackSize = context.stackSize(); normFile.installName = context.installName(); normFile.currentVersion = context.currentVersion(); normFile.compatVersion = context.compatibilityVersion(); normFile.os = context.os(); // If we are emitting an object file, then the min version is the maximum // of the min's of all the source files and the cmdline. if (normFile.fileType == llvm::MachO::MH_OBJECT) normFile.minOSverson = std::max(context.osMinVersion(), util.minVersion()); else normFile.minOSverson = context.osMinVersion(); normFile.minOSVersionKind = util.minVersionCommandType(); normFile.sdkVersion = context.sdkVersion(); normFile.sourceVersion = context.sourceVersion(); if (context.generateVersionLoadCommand() && context.os() != MachOLinkingContext::OS::unknown) normFile.hasMinVersionLoadCommand = true; else if (normFile.fileType == llvm::MachO::MH_OBJECT && util.allSourceFilesHaveMinVersions() && ((normFile.os != MachOLinkingContext::OS::unknown) || util.minVersionCommandType())) { // If we emit an object file, then it should contain a min version load // command if all of the source files also contained min version commands. // Also, we either need to have a platform, or found a platform from the // source object files. normFile.hasMinVersionLoadCommand = true; } normFile.generateDataInCodeLoadCommand = context.generateDataInCodeLoadCommand(); normFile.pageSize = context.pageSize(); normFile.rpaths = context.rpaths(); util.addDependentDylibs(atomFile, normFile); util.copySegmentInfo(normFile); util.copySectionInfo(normFile); util.assignAddressesToSections(normFile); util.buildAtomToAddressMap(); if (auto err = util.synthesizeDebugNotes(normFile)) return std::move(err); util.updateSectionInfo(normFile); util.copySectionContent(normFile); if (auto ec = util.addSymbols(atomFile, normFile)) { return std::move(ec); } util.addIndirectSymbols(atomFile, normFile); util.addRebaseAndBindingInfo(atomFile, normFile); util.addExportInfo(atomFile, normFile); util.addSectionRelocs(atomFile, normFile); util.addFunctionStarts(atomFile, normFile); util.buildDataInCodeArray(atomFile, normFile); util.copyEntryPointAddress(normFile); return std::move(f); } } // namespace normalized } // namespace mach_o } // namespace lld Index: head/contrib/llvm/tools/lld =================================================================== --- head/contrib/llvm/tools/lld (revision 326908) +++ head/contrib/llvm/tools/lld (revision 326909) Property changes on: head/contrib/llvm/tools/lld ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /vendor/lld/dist:r326471-326907 Index: head/contrib/llvm/tools/lldb =================================================================== --- head/contrib/llvm/tools/lldb (revision 326908) +++ head/contrib/llvm/tools/lldb (revision 326909) Property changes on: head/contrib/llvm/tools/lldb ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /vendor/lldb/dist:r326471-326907 Index: head/contrib/llvm =================================================================== --- head/contrib/llvm (revision 326908) +++ head/contrib/llvm (revision 326909) Property changes on: head/contrib/llvm ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /vendor/llvm/dist:r326471-326907 Index: head/lib/clang/include/clang/Basic/Version.inc =================================================================== --- head/lib/clang/include/clang/Basic/Version.inc (revision 326908) +++ head/lib/clang/include/clang/Basic/Version.inc (revision 326909) @@ -1,11 +1,11 @@ /* $FreeBSD$ */ #define CLANG_VERSION 5.0.1 #define CLANG_VERSION_STRING "5.0.1" #define CLANG_VERSION_MAJOR 5 #define CLANG_VERSION_MINOR 0 #define CLANG_VERSION_PATCHLEVEL 1 #define CLANG_VENDOR "FreeBSD " -#define SVN_REVISION "319231" +#define SVN_REVISION "320880" Index: head/lib/clang/include/lld/Config/Version.inc =================================================================== --- head/lib/clang/include/lld/Config/Version.inc (revision 326908) +++ head/lib/clang/include/lld/Config/Version.inc (revision 326909) @@ -1,8 +1,8 @@ // $FreeBSD$ #define LLD_VERSION 5.0.1 #define LLD_VERSION_STRING "5.0.1" #define LLD_VERSION_MAJOR 5 #define LLD_VERSION_MINOR 0 -#define LLD_REVISION_STRING "319231" +#define LLD_REVISION_STRING "320880" #define LLD_REPOSITORY_STRING "FreeBSD" Index: head/lib/clang/include/llvm/Support/VCSRevision.h =================================================================== --- head/lib/clang/include/llvm/Support/VCSRevision.h (revision 326908) +++ head/lib/clang/include/llvm/Support/VCSRevision.h (revision 326909) @@ -1,2 +1,2 @@ /* $FreeBSD$ */ -#define LLVM_REVISION "svn-r319231" +#define LLVM_REVISION "svn-r320880"