| Hans Wennborg | dcfba33 | 2015-10-06 23:40:43 +0000 | [diff] [blame] | 1 | //===--- CGClass.cpp - Emit LLVM Code for C++ classes -----------*- C++ -*-===// | 
| Anders Carlsson | 9a57c5a | 2009-09-12 04:27:24 +0000 | [diff] [blame] | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This contains code dealing with C++ code generation of classes | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
| Eli Friedman | 2495ab0 | 2012-02-25 02:48:22 +0000 | [diff] [blame] | 14 | #include "CGBlocks.h" | 
| Chandler Carruth | 5553d0d | 2014-01-07 11:51:46 +0000 | [diff] [blame] | 15 | #include "CGCXXABI.h" | 
| Devang Patel | d76c1db | 2010-08-11 21:04:37 +0000 | [diff] [blame] | 16 | #include "CGDebugInfo.h" | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 17 | #include "CGRecordLayout.h" | 
| Anders Carlsson | 9a57c5a | 2009-09-12 04:27:24 +0000 | [diff] [blame] | 18 | #include "CodeGenFunction.h" | 
| Anders Carlsson | c6d171e | 2009-10-06 22:43:30 +0000 | [diff] [blame] | 19 | #include "clang/AST/CXXInheritance.h" | 
| Faisal Vali | 571df12 | 2013-09-29 08:45:24 +0000 | [diff] [blame] | 20 | #include "clang/AST/DeclTemplate.h" | 
| John McCall | 769250e | 2010-09-17 02:31:44 +0000 | [diff] [blame] | 21 | #include "clang/AST/EvaluatedExprVisitor.h" | 
| Anders Carlsson | 9a57c5a | 2009-09-12 04:27:24 +0000 | [diff] [blame] | 22 | #include "clang/AST/RecordLayout.h" | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 23 | #include "clang/AST/StmtCXX.h" | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 24 | #include "clang/Basic/TargetBuiltins.h" | 
| Mark Lacey | a8e7df3 | 2013-10-30 21:53:58 +0000 | [diff] [blame] | 25 | #include "clang/CodeGen/CGFunctionInfo.h" | 
| Saleem Abdulrasool | 10a4972 | 2016-04-08 16:52:00 +0000 | [diff] [blame] | 26 | #include "clang/Frontend/CodeGenOptions.h" | 
| Peter Collingbourne | a4ccff3 | 2015-02-20 20:30:56 +0000 | [diff] [blame] | 27 | #include "llvm/IR/Intrinsics.h" | 
| Piotr Padlewski | 4b1ac72 | 2015-09-15 21:46:55 +0000 | [diff] [blame] | 28 | #include "llvm/IR/Metadata.h" | 
| Peter Collingbourne | dc13453 | 2016-01-16 00:31:22 +0000 | [diff] [blame] | 29 | #include "llvm/Transforms/Utils/SanitizerStats.h" | 
| Anders Carlsson | c6d171e | 2009-10-06 22:43:30 +0000 | [diff] [blame] | 30 |  | 
| Anders Carlsson | 9a57c5a | 2009-09-12 04:27:24 +0000 | [diff] [blame] | 31 | using namespace clang; | 
|  | 32 | using namespace CodeGen; | 
|  | 33 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 34 | /// Return the best known alignment for an unknown pointer to a | 
|  | 35 | /// particular class. | 
|  | 36 | CharUnits CodeGenModule::getClassPointerAlignment(const CXXRecordDecl *RD) { | 
|  | 37 | if (!RD->isCompleteDefinition()) | 
|  | 38 | return CharUnits::One(); // Hopefully won't be used anywhere. | 
|  | 39 |  | 
|  | 40 | auto &layout = getContext().getASTRecordLayout(RD); | 
|  | 41 |  | 
|  | 42 | // If the class is final, then we know that the pointer points to an | 
|  | 43 | // object of that type and can use the full alignment. | 
|  | 44 | if (RD->hasAttr<FinalAttr>()) { | 
|  | 45 | return layout.getAlignment(); | 
|  | 46 |  | 
|  | 47 | // Otherwise, we have to assume it could be a subclass. | 
|  | 48 | } else { | 
|  | 49 | return layout.getNonVirtualAlignment(); | 
|  | 50 | } | 
|  | 51 | } | 
|  | 52 |  | 
|  | 53 | /// Return the best known alignment for a pointer to a virtual base, | 
|  | 54 | /// given the alignment of a pointer to the derived class. | 
|  | 55 | CharUnits CodeGenModule::getVBaseAlignment(CharUnits actualDerivedAlign, | 
|  | 56 | const CXXRecordDecl *derivedClass, | 
|  | 57 | const CXXRecordDecl *vbaseClass) { | 
|  | 58 | // The basic idea here is that an underaligned derived pointer might | 
|  | 59 | // indicate an underaligned base pointer. | 
|  | 60 |  | 
|  | 61 | assert(vbaseClass->isCompleteDefinition()); | 
|  | 62 | auto &baseLayout = getContext().getASTRecordLayout(vbaseClass); | 
|  | 63 | CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment(); | 
|  | 64 |  | 
|  | 65 | return getDynamicOffsetAlignment(actualDerivedAlign, derivedClass, | 
|  | 66 | expectedVBaseAlign); | 
|  | 67 | } | 
|  | 68 |  | 
|  | 69 | CharUnits | 
|  | 70 | CodeGenModule::getDynamicOffsetAlignment(CharUnits actualBaseAlign, | 
|  | 71 | const CXXRecordDecl *baseDecl, | 
|  | 72 | CharUnits expectedTargetAlign) { | 
|  | 73 | // If the base is an incomplete type (which is, alas, possible with | 
|  | 74 | // member pointers), be pessimistic. | 
|  | 75 | if (!baseDecl->isCompleteDefinition()) | 
|  | 76 | return std::min(actualBaseAlign, expectedTargetAlign); | 
|  | 77 |  | 
|  | 78 | auto &baseLayout = getContext().getASTRecordLayout(baseDecl); | 
|  | 79 | CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment(); | 
|  | 80 |  | 
|  | 81 | // If the class is properly aligned, assume the target offset is, too. | 
|  | 82 | // | 
|  | 83 | // This actually isn't necessarily the right thing to do --- if the | 
|  | 84 | // class is a complete object, but it's only properly aligned for a | 
|  | 85 | // base subobject, then the alignments of things relative to it are | 
|  | 86 | // probably off as well.  (Note that this requires the alignment of | 
|  | 87 | // the target to be greater than the NV alignment of the derived | 
|  | 88 | // class.) | 
|  | 89 | // | 
|  | 90 | // However, our approach to this kind of under-alignment can only | 
|  | 91 | // ever be best effort; after all, we're never going to propagate | 
|  | 92 | // alignments through variables or parameters.  Note, in particular, | 
|  | 93 | // that constructing a polymorphic type in an address that's less | 
|  | 94 | // than pointer-aligned will generally trap in the constructor, | 
|  | 95 | // unless we someday add some sort of attribute to change the | 
|  | 96 | // assumed alignment of 'this'.  So our goal here is pretty much | 
|  | 97 | // just to allow the user to explicitly say that a pointer is | 
| Eric Christopher | d160c50 | 2016-01-29 01:35:53 +0000 | [diff] [blame] | 98 | // under-aligned and then safely access its fields and vtables. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 99 | if (actualBaseAlign >= expectedBaseAlign) { | 
|  | 100 | return expectedTargetAlign; | 
|  | 101 | } | 
|  | 102 |  | 
|  | 103 | // Otherwise, we might be offset by an arbitrary multiple of the | 
|  | 104 | // actual alignment.  The correct adjustment is to take the min of | 
|  | 105 | // the two alignments. | 
|  | 106 | return std::min(actualBaseAlign, expectedTargetAlign); | 
|  | 107 | } | 
|  | 108 |  | 
|  | 109 | Address CodeGenFunction::LoadCXXThisAddress() { | 
|  | 110 | assert(CurFuncDecl && "loading 'this' without a func declaration?"); | 
|  | 111 | assert(isa<CXXMethodDecl>(CurFuncDecl)); | 
|  | 112 |  | 
|  | 113 | // Lazily compute CXXThisAlignment. | 
|  | 114 | if (CXXThisAlignment.isZero()) { | 
|  | 115 | // Just use the best known alignment for the parent. | 
|  | 116 | // TODO: if we're currently emitting a complete-object ctor/dtor, | 
|  | 117 | // we can always use the complete-object alignment. | 
|  | 118 | auto RD = cast<CXXMethodDecl>(CurFuncDecl)->getParent(); | 
|  | 119 | CXXThisAlignment = CGM.getClassPointerAlignment(RD); | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | return Address(LoadCXXThis(), CXXThisAlignment); | 
|  | 123 | } | 
|  | 124 |  | 
|  | 125 | /// Emit the address of a field using a member data pointer. | 
|  | 126 | /// | 
|  | 127 | /// \param E Only used for emergency diagnostics | 
|  | 128 | Address | 
|  | 129 | CodeGenFunction::EmitCXXMemberDataPointerAddress(const Expr *E, Address base, | 
|  | 130 | llvm::Value *memberPtr, | 
|  | 131 | const MemberPointerType *memberPtrType, | 
| Ivan A. Kosarev | 229a6d8 | 2017-10-13 16:38:32 +0000 | [diff] [blame] | 132 | LValueBaseInfo *BaseInfo, | 
|  | 133 | TBAAAccessInfo *TBAAInfo) { | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 134 | // Ask the ABI to compute the actual address. | 
|  | 135 | llvm::Value *ptr = | 
|  | 136 | CGM.getCXXABI().EmitMemberDataPointerAddress(*this, E, base, | 
|  | 137 | memberPtr, memberPtrType); | 
|  | 138 |  | 
|  | 139 | QualType memberType = memberPtrType->getPointeeType(); | 
| Ivan A. Kosarev | 78f486d | 2017-10-13 16:58:30 +0000 | [diff] [blame] | 140 | CharUnits memberAlign = getNaturalTypeAlignment(memberType, BaseInfo, | 
|  | 141 | TBAAInfo); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 142 | memberAlign = | 
|  | 143 | CGM.getDynamicOffsetAlignment(base.getAlignment(), | 
|  | 144 | memberPtrType->getClass()->getAsCXXRecordDecl(), | 
|  | 145 | memberAlign); | 
|  | 146 | return Address(ptr, memberAlign); | 
|  | 147 | } | 
|  | 148 |  | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 149 | CharUnits CodeGenModule::computeNonVirtualBaseClassOffset( | 
|  | 150 | const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start, | 
|  | 151 | CastExpr::path_const_iterator End) { | 
| Ken Dyck | a1a4ae3 | 2011-03-22 00:53:26 +0000 | [diff] [blame] | 152 | CharUnits Offset = CharUnits::Zero(); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 153 |  | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 154 | const ASTContext &Context = getContext(); | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 155 | const CXXRecordDecl *RD = DerivedClass; | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 156 |  | 
| John McCall | cf14216 | 2010-08-07 06:22:56 +0000 | [diff] [blame] | 157 | for (CastExpr::path_const_iterator I = Start; I != End; ++I) { | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 158 | const CXXBaseSpecifier *Base = *I; | 
|  | 159 | assert(!Base->isVirtual() && "Should not see virtual bases here!"); | 
|  | 160 |  | 
|  | 161 | // Get the layout. | 
|  | 162 | const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 163 |  | 
|  | 164 | const CXXRecordDecl *BaseDecl = | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 165 | cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 166 |  | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 167 | // Add the offset. | 
| Ken Dyck | a1a4ae3 | 2011-03-22 00:53:26 +0000 | [diff] [blame] | 168 | Offset += Layout.getBaseClassOffset(BaseDecl); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 169 |  | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 170 | RD = BaseDecl; | 
|  | 171 | } | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 172 |  | 
| Ken Dyck | a1a4ae3 | 2011-03-22 00:53:26 +0000 | [diff] [blame] | 173 | return Offset; | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 174 | } | 
| Anders Carlsson | 9a57c5a | 2009-09-12 04:27:24 +0000 | [diff] [blame] | 175 |  | 
| Anders Carlsson | 9150a2a | 2009-09-29 03:13:20 +0000 | [diff] [blame] | 176 | llvm::Constant * | 
| Anders Carlsson | 8a64c1c | 2010-04-24 21:23:59 +0000 | [diff] [blame] | 177 | CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl, | 
| John McCall | cf14216 | 2010-08-07 06:22:56 +0000 | [diff] [blame] | 178 | CastExpr::path_const_iterator PathBegin, | 
|  | 179 | CastExpr::path_const_iterator PathEnd) { | 
|  | 180 | assert(PathBegin != PathEnd && "Base path should not be empty!"); | 
| Anders Carlsson | 8a64c1c | 2010-04-24 21:23:59 +0000 | [diff] [blame] | 181 |  | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 182 | CharUnits Offset = | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 183 | computeNonVirtualBaseClassOffset(ClassDecl, PathBegin, PathEnd); | 
| Ken Dyck | a1a4ae3 | 2011-03-22 00:53:26 +0000 | [diff] [blame] | 184 | if (Offset.isZero()) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 185 | return nullptr; | 
|  | 186 |  | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 187 | llvm::Type *PtrDiffTy = | 
| Anders Carlsson | 8a64c1c | 2010-04-24 21:23:59 +0000 | [diff] [blame] | 188 | Types.ConvertType(getContext().getPointerDiffType()); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 189 |  | 
| Ken Dyck | a1a4ae3 | 2011-03-22 00:53:26 +0000 | [diff] [blame] | 190 | return llvm::ConstantInt::get(PtrDiffTy, Offset.getQuantity()); | 
| Anders Carlsson | 9150a2a | 2009-09-29 03:13:20 +0000 | [diff] [blame] | 191 | } | 
|  | 192 |  | 
| Anders Carlsson | c4ba0cd | 2010-04-24 23:01:49 +0000 | [diff] [blame] | 193 | /// Gets the address of a direct base class within a complete object. | 
| John McCall | 6ce7472 | 2010-02-16 04:15:37 +0000 | [diff] [blame] | 194 | /// This should only be used for (1) non-virtual bases or (2) virtual bases | 
|  | 195 | /// when the type is known to be complete (e.g. in complete destructors). | 
|  | 196 | /// | 
|  | 197 | /// The object pointed to by 'This' is assumed to be non-null. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 198 | Address | 
|  | 199 | CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(Address This, | 
| Anders Carlsson | c4ba0cd | 2010-04-24 23:01:49 +0000 | [diff] [blame] | 200 | const CXXRecordDecl *Derived, | 
|  | 201 | const CXXRecordDecl *Base, | 
|  | 202 | bool BaseIsVirtual) { | 
| John McCall | 6ce7472 | 2010-02-16 04:15:37 +0000 | [diff] [blame] | 203 | // 'this' must be a pointer (in some address space) to Derived. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 204 | assert(This.getElementType() == ConvertType(Derived)); | 
| John McCall | 6ce7472 | 2010-02-16 04:15:37 +0000 | [diff] [blame] | 205 |  | 
|  | 206 | // Compute the offset of the virtual base. | 
| Ken Dyck | 6aa767c | 2011-03-22 01:21:15 +0000 | [diff] [blame] | 207 | CharUnits Offset; | 
| John McCall | 6ce7472 | 2010-02-16 04:15:37 +0000 | [diff] [blame] | 208 | const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Derived); | 
| Anders Carlsson | c4ba0cd | 2010-04-24 23:01:49 +0000 | [diff] [blame] | 209 | if (BaseIsVirtual) | 
| Ken Dyck | 6aa767c | 2011-03-22 01:21:15 +0000 | [diff] [blame] | 210 | Offset = Layout.getVBaseClassOffset(Base); | 
| John McCall | 6ce7472 | 2010-02-16 04:15:37 +0000 | [diff] [blame] | 211 | else | 
| Ken Dyck | 6aa767c | 2011-03-22 01:21:15 +0000 | [diff] [blame] | 212 | Offset = Layout.getBaseClassOffset(Base); | 
| John McCall | 6ce7472 | 2010-02-16 04:15:37 +0000 | [diff] [blame] | 213 |  | 
|  | 214 | // Shift and cast down to the base type. | 
|  | 215 | // TODO: for complete types, this should be possible with a GEP. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 216 | Address V = This; | 
|  | 217 | if (!Offset.isZero()) { | 
|  | 218 | V = Builder.CreateElementBitCast(V, Int8Ty); | 
|  | 219 | V = Builder.CreateConstInBoundsByteGEP(V, Offset); | 
| John McCall | 6ce7472 | 2010-02-16 04:15:37 +0000 | [diff] [blame] | 220 | } | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 221 | V = Builder.CreateElementBitCast(V, ConvertType(Base)); | 
| John McCall | 6ce7472 | 2010-02-16 04:15:37 +0000 | [diff] [blame] | 222 |  | 
|  | 223 | return V; | 
| Anders Carlsson | e87fae9 | 2010-03-28 19:40:00 +0000 | [diff] [blame] | 224 | } | 
| John McCall | 6ce7472 | 2010-02-16 04:15:37 +0000 | [diff] [blame] | 225 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 226 | static Address | 
|  | 227 | ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr, | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 228 | CharUnits nonVirtualOffset, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 229 | llvm::Value *virtualOffset, | 
|  | 230 | const CXXRecordDecl *derivedClass, | 
|  | 231 | const CXXRecordDecl *nearestVBase) { | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 232 | // Assert that we have something to do. | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 233 | assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr); | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 234 |  | 
|  | 235 | // Compute the offset from the static and dynamic components. | 
|  | 236 | llvm::Value *baseOffset; | 
|  | 237 | if (!nonVirtualOffset.isZero()) { | 
|  | 238 | baseOffset = llvm::ConstantInt::get(CGF.PtrDiffTy, | 
|  | 239 | nonVirtualOffset.getQuantity()); | 
|  | 240 | if (virtualOffset) { | 
|  | 241 | baseOffset = CGF.Builder.CreateAdd(virtualOffset, baseOffset); | 
|  | 242 | } | 
|  | 243 | } else { | 
|  | 244 | baseOffset = virtualOffset; | 
|  | 245 | } | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 246 |  | 
| Anders Carlsson | 53cebd1 | 2010-04-20 16:03:35 +0000 | [diff] [blame] | 247 | // Apply the base offset. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 248 | llvm::Value *ptr = addr.getPointer(); | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 249 | ptr = CGF.Builder.CreateBitCast(ptr, CGF.Int8PtrTy); | 
|  | 250 | ptr = CGF.Builder.CreateInBoundsGEP(ptr, baseOffset, "add.ptr"); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 251 |  | 
|  | 252 | // If we have a virtual component, the alignment of the result will | 
|  | 253 | // be relative only to the known alignment of that vbase. | 
|  | 254 | CharUnits alignment; | 
|  | 255 | if (virtualOffset) { | 
|  | 256 | assert(nearestVBase && "virtual offset without vbase?"); | 
|  | 257 | alignment = CGF.CGM.getVBaseAlignment(addr.getAlignment(), | 
|  | 258 | derivedClass, nearestVBase); | 
|  | 259 | } else { | 
|  | 260 | alignment = addr.getAlignment(); | 
|  | 261 | } | 
|  | 262 | alignment = alignment.alignmentAtOffset(nonVirtualOffset); | 
|  | 263 |  | 
|  | 264 | return Address(ptr, alignment); | 
| Anders Carlsson | 53cebd1 | 2010-04-20 16:03:35 +0000 | [diff] [blame] | 265 | } | 
|  | 266 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 267 | Address CodeGenFunction::GetAddressOfBaseClass( | 
|  | 268 | Address Value, const CXXRecordDecl *Derived, | 
| Alexey Samsonov | eb47d8a | 2014-10-13 23:59:00 +0000 | [diff] [blame] | 269 | CastExpr::path_const_iterator PathBegin, | 
|  | 270 | CastExpr::path_const_iterator PathEnd, bool NullCheckValue, | 
|  | 271 | SourceLocation Loc) { | 
| John McCall | cf14216 | 2010-08-07 06:22:56 +0000 | [diff] [blame] | 272 | assert(PathBegin != PathEnd && "Base path should not be empty!"); | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 273 |  | 
| John McCall | cf14216 | 2010-08-07 06:22:56 +0000 | [diff] [blame] | 274 | CastExpr::path_const_iterator Start = PathBegin; | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 275 | const CXXRecordDecl *VBase = nullptr; | 
|  | 276 |  | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 277 | // Sema has done some convenient canonicalization here: if the | 
|  | 278 | // access path involved any virtual steps, the conversion path will | 
|  | 279 | // *start* with a step down to the correct virtual base subobject, | 
|  | 280 | // and hence will not require any further steps. | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 281 | if ((*Start)->isVirtual()) { | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 282 | VBase = | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 283 | cast<CXXRecordDecl>((*Start)->getType()->getAs<RecordType>()->getDecl()); | 
|  | 284 | ++Start; | 
|  | 285 | } | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 286 |  | 
|  | 287 | // Compute the static offset of the ultimate destination within its | 
|  | 288 | // allocating subobject (the virtual base, if there is one, or else | 
|  | 289 | // the "complete" object that we see). | 
| David Majnemer | c1709d3 | 2015-06-23 07:31:11 +0000 | [diff] [blame] | 290 | CharUnits NonVirtualOffset = CGM.computeNonVirtualBaseClassOffset( | 
|  | 291 | VBase ? VBase : Derived, Start, PathEnd); | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 292 |  | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 293 | // If there's a virtual step, we can sometimes "devirtualize" it. | 
|  | 294 | // For now, that's limited to when the derived type is final. | 
|  | 295 | // TODO: "devirtualize" this for accesses to known-complete objects. | 
|  | 296 | if (VBase && Derived->hasAttr<FinalAttr>()) { | 
|  | 297 | const ASTRecordLayout &layout = getContext().getASTRecordLayout(Derived); | 
|  | 298 | CharUnits vBaseOffset = layout.getVBaseClassOffset(VBase); | 
|  | 299 | NonVirtualOffset += vBaseOffset; | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 300 | VBase = nullptr; // we no longer have a virtual step | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 301 | } | 
|  | 302 |  | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 303 | // Get the base pointer type. | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 304 | llvm::Type *BasePtrTy = | 
| John McCall | cf14216 | 2010-08-07 06:22:56 +0000 | [diff] [blame] | 305 | ConvertType((PathEnd[-1])->getType())->getPointerTo(); | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 306 |  | 
| Alexey Samsonov | eb47d8a | 2014-10-13 23:59:00 +0000 | [diff] [blame] | 307 | QualType DerivedTy = getContext().getRecordType(Derived); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 308 | CharUnits DerivedAlign = CGM.getClassPointerAlignment(Derived); | 
| Alexey Samsonov | eb47d8a | 2014-10-13 23:59:00 +0000 | [diff] [blame] | 309 |  | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 310 | // If the static offset is zero and we don't have a virtual step, | 
|  | 311 | // just do a bitcast; null checks are unnecessary. | 
| Ken Dyck | a1a4ae3 | 2011-03-22 00:53:26 +0000 | [diff] [blame] | 312 | if (NonVirtualOffset.isZero() && !VBase) { | 
| Alexey Samsonov | eb47d8a | 2014-10-13 23:59:00 +0000 | [diff] [blame] | 313 | if (sanitizePerformTypeCheck()) { | 
| Vedant Kumar | 18348ea | 2017-02-17 23:22:55 +0000 | [diff] [blame] | 314 | SanitizerSet SkippedChecks; | 
|  | 315 | SkippedChecks.set(SanitizerKind::Null, !NullCheckValue); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 316 | EmitTypeCheck(TCK_Upcast, Loc, Value.getPointer(), | 
| Vedant Kumar | 18348ea | 2017-02-17 23:22:55 +0000 | [diff] [blame] | 317 | DerivedTy, DerivedAlign, SkippedChecks); | 
| Alexey Samsonov | eb47d8a | 2014-10-13 23:59:00 +0000 | [diff] [blame] | 318 | } | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 319 | return Builder.CreateBitCast(Value, BasePtrTy); | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 320 | } | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 321 |  | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 322 | llvm::BasicBlock *origBB = nullptr; | 
|  | 323 | llvm::BasicBlock *endBB = nullptr; | 
|  | 324 |  | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 325 | // Skip over the offset (and the vtable load) if we're supposed to | 
|  | 326 | // null-check the pointer. | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 327 | if (NullCheckValue) { | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 328 | origBB = Builder.GetInsertBlock(); | 
|  | 329 | llvm::BasicBlock *notNullBB = createBasicBlock("cast.notnull"); | 
|  | 330 | endBB = createBasicBlock("cast.end"); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 331 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 332 | llvm::Value *isNull = Builder.CreateIsNull(Value.getPointer()); | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 333 | Builder.CreateCondBr(isNull, endBB, notNullBB); | 
|  | 334 | EmitBlock(notNullBB); | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 335 | } | 
|  | 336 |  | 
| Alexey Samsonov | eb47d8a | 2014-10-13 23:59:00 +0000 | [diff] [blame] | 337 | if (sanitizePerformTypeCheck()) { | 
| Vedant Kumar | 18348ea | 2017-02-17 23:22:55 +0000 | [diff] [blame] | 338 | SanitizerSet SkippedChecks; | 
|  | 339 | SkippedChecks.set(SanitizerKind::Null, true); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 340 | EmitTypeCheck(VBase ? TCK_UpcastToVirtualBase : TCK_Upcast, Loc, | 
| Vedant Kumar | 18348ea | 2017-02-17 23:22:55 +0000 | [diff] [blame] | 341 | Value.getPointer(), DerivedTy, DerivedAlign, SkippedChecks); | 
| Alexey Samsonov | eb47d8a | 2014-10-13 23:59:00 +0000 | [diff] [blame] | 342 | } | 
|  | 343 |  | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 344 | // Compute the virtual offset. | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 345 | llvm::Value *VirtualOffset = nullptr; | 
| Anders Carlsson | a376b53 | 2011-01-29 03:18:56 +0000 | [diff] [blame] | 346 | if (VBase) { | 
| Reid Kleckner | d8cbeec | 2013-05-29 18:02:47 +0000 | [diff] [blame] | 347 | VirtualOffset = | 
|  | 348 | CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase); | 
| Anders Carlsson | a376b53 | 2011-01-29 03:18:56 +0000 | [diff] [blame] | 349 | } | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 350 |  | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 351 | // Apply both offsets. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 352 | Value = ApplyNonVirtualAndVirtualOffset(*this, Value, NonVirtualOffset, | 
|  | 353 | VirtualOffset, Derived, VBase); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 354 |  | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 355 | // Cast to the destination type. | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 356 | Value = Builder.CreateBitCast(Value, BasePtrTy); | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 357 |  | 
|  | 358 | // Build a phi if we needed a null check. | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 359 | if (NullCheckValue) { | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 360 | llvm::BasicBlock *notNullBB = Builder.GetInsertBlock(); | 
|  | 361 | Builder.CreateBr(endBB); | 
|  | 362 | EmitBlock(endBB); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 363 |  | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 364 | llvm::PHINode *PHI = Builder.CreatePHI(BasePtrTy, 2, "cast.result"); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 365 | PHI->addIncoming(Value.getPointer(), notNullBB); | 
| John McCall | 13a39c6 | 2012-08-01 05:04:58 +0000 | [diff] [blame] | 366 | PHI->addIncoming(llvm::Constant::getNullValue(BasePtrTy), origBB); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 367 | Value = Address(PHI, Value.getAlignment()); | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 368 | } | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 369 |  | 
| Anders Carlsson | d829a02 | 2010-04-24 21:06:20 +0000 | [diff] [blame] | 370 | return Value; | 
|  | 371 | } | 
|  | 372 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 373 | Address | 
|  | 374 | CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr, | 
| Anders Carlsson | c4ba0cd | 2010-04-24 23:01:49 +0000 | [diff] [blame] | 375 | const CXXRecordDecl *Derived, | 
| John McCall | cf14216 | 2010-08-07 06:22:56 +0000 | [diff] [blame] | 376 | CastExpr::path_const_iterator PathBegin, | 
|  | 377 | CastExpr::path_const_iterator PathEnd, | 
| Anders Carlsson | 8c79317 | 2009-11-23 17:57:54 +0000 | [diff] [blame] | 378 | bool NullCheckValue) { | 
| John McCall | cf14216 | 2010-08-07 06:22:56 +0000 | [diff] [blame] | 379 | assert(PathBegin != PathEnd && "Base path should not be empty!"); | 
| Anders Carlsson | 8a64c1c | 2010-04-24 21:23:59 +0000 | [diff] [blame] | 380 |  | 
| Anders Carlsson | 8c79317 | 2009-11-23 17:57:54 +0000 | [diff] [blame] | 381 | QualType DerivedTy = | 
| Anders Carlsson | c4ba0cd | 2010-04-24 23:01:49 +0000 | [diff] [blame] | 382 | getContext().getCanonicalType(getContext().getTagDeclType(Derived)); | 
| Chris Lattner | 2192fe5 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 383 | llvm::Type *DerivedPtrTy = ConvertType(DerivedTy)->getPointerTo(); | 
| Richard Smith | 2c5868c | 2013-02-13 21:18:23 +0000 | [diff] [blame] | 384 |  | 
| Anders Carlsson | 600f737 | 2010-01-31 01:43:37 +0000 | [diff] [blame] | 385 | llvm::Value *NonVirtualOffset = | 
| John McCall | cf14216 | 2010-08-07 06:22:56 +0000 | [diff] [blame] | 386 | CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 387 |  | 
| Anders Carlsson | 600f737 | 2010-01-31 01:43:37 +0000 | [diff] [blame] | 388 | if (!NonVirtualOffset) { | 
|  | 389 | // No offset, we can just cast back. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 390 | return Builder.CreateBitCast(BaseAddr, DerivedPtrTy); | 
| Anders Carlsson | 600f737 | 2010-01-31 01:43:37 +0000 | [diff] [blame] | 391 | } | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 392 |  | 
|  | 393 | llvm::BasicBlock *CastNull = nullptr; | 
|  | 394 | llvm::BasicBlock *CastNotNull = nullptr; | 
|  | 395 | llvm::BasicBlock *CastEnd = nullptr; | 
|  | 396 |  | 
| Anders Carlsson | 8c79317 | 2009-11-23 17:57:54 +0000 | [diff] [blame] | 397 | if (NullCheckValue) { | 
|  | 398 | CastNull = createBasicBlock("cast.null"); | 
|  | 399 | CastNotNull = createBasicBlock("cast.notnull"); | 
|  | 400 | CastEnd = createBasicBlock("cast.end"); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 401 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 402 | llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr.getPointer()); | 
| Anders Carlsson | 8c79317 | 2009-11-23 17:57:54 +0000 | [diff] [blame] | 403 | Builder.CreateCondBr(IsNull, CastNull, CastNotNull); | 
|  | 404 | EmitBlock(CastNotNull); | 
|  | 405 | } | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 406 |  | 
| Anders Carlsson | 600f737 | 2010-01-31 01:43:37 +0000 | [diff] [blame] | 407 | // Apply the offset. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 408 | llvm::Value *Value = Builder.CreateBitCast(BaseAddr.getPointer(), Int8PtrTy); | 
| Sanjay Patel | 372c3f1 | 2018-01-19 15:14:51 +0000 | [diff] [blame] | 409 | Value = Builder.CreateInBoundsGEP(Value, Builder.CreateNeg(NonVirtualOffset), | 
|  | 410 | "sub.ptr"); | 
| Anders Carlsson | 600f737 | 2010-01-31 01:43:37 +0000 | [diff] [blame] | 411 |  | 
|  | 412 | // Just cast. | 
|  | 413 | Value = Builder.CreateBitCast(Value, DerivedPtrTy); | 
| Anders Carlsson | 8c79317 | 2009-11-23 17:57:54 +0000 | [diff] [blame] | 414 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 415 | // Produce a PHI if we had a null-check. | 
| Anders Carlsson | 8c79317 | 2009-11-23 17:57:54 +0000 | [diff] [blame] | 416 | if (NullCheckValue) { | 
|  | 417 | Builder.CreateBr(CastEnd); | 
|  | 418 | EmitBlock(CastNull); | 
|  | 419 | Builder.CreateBr(CastEnd); | 
|  | 420 | EmitBlock(CastEnd); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 421 |  | 
| Jay Foad | 20c0f02 | 2011-03-30 11:28:58 +0000 | [diff] [blame] | 422 | llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2); | 
| Anders Carlsson | 8c79317 | 2009-11-23 17:57:54 +0000 | [diff] [blame] | 423 | PHI->addIncoming(Value, CastNotNull); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 424 | PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull); | 
| Anders Carlsson | 8c79317 | 2009-11-23 17:57:54 +0000 | [diff] [blame] | 425 | Value = PHI; | 
|  | 426 | } | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 427 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 428 | return Address(Value, CGM.getClassPointerAlignment(Derived)); | 
| Anders Carlsson | 9a57c5a | 2009-09-12 04:27:24 +0000 | [diff] [blame] | 429 | } | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 430 |  | 
|  | 431 | llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD, | 
|  | 432 | bool ForVirtualBase, | 
|  | 433 | bool Delegating) { | 
| Peter Collingbourne | 66f82e6 | 2013-06-28 20:45:28 +0000 | [diff] [blame] | 434 | if (!CGM.getCXXABI().NeedsVTTParameter(GD)) { | 
| Anders Carlsson | e36a6b3 | 2010-01-02 01:01:18 +0000 | [diff] [blame] | 435 | // This constructor/destructor does not need a VTT parameter. | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 436 | return nullptr; | 
| Anders Carlsson | e36a6b3 | 2010-01-02 01:01:18 +0000 | [diff] [blame] | 437 | } | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 438 |  | 
| John McCall | dec348f7 | 2013-05-03 07:33:41 +0000 | [diff] [blame] | 439 | const CXXRecordDecl *RD = cast<CXXMethodDecl>(CurCodeDecl)->getParent(); | 
| Anders Carlsson | e36a6b3 | 2010-01-02 01:01:18 +0000 | [diff] [blame] | 440 | const CXXRecordDecl *Base = cast<CXXMethodDecl>(GD.getDecl())->getParent(); | 
| John McCall | 5c60a6f | 2010-02-18 19:59:28 +0000 | [diff] [blame] | 441 |  | 
| Anders Carlsson | e36a6b3 | 2010-01-02 01:01:18 +0000 | [diff] [blame] | 442 | llvm::Value *VTT; | 
|  | 443 |  | 
| John McCall | 5c60a6f | 2010-02-18 19:59:28 +0000 | [diff] [blame] | 444 | uint64_t SubVTTIndex; | 
|  | 445 |  | 
| Douglas Gregor | 6153500 | 2013-01-31 05:50:40 +0000 | [diff] [blame] | 446 | if (Delegating) { | 
|  | 447 | // If this is a delegating constructor call, just load the VTT. | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 448 | return LoadCXXVTT(); | 
| Douglas Gregor | 6153500 | 2013-01-31 05:50:40 +0000 | [diff] [blame] | 449 | } else if (RD == Base) { | 
|  | 450 | // If the record matches the base, this is the complete ctor/dtor | 
|  | 451 | // variant calling the base variant in a class with virtual bases. | 
| Peter Collingbourne | 66f82e6 | 2013-06-28 20:45:28 +0000 | [diff] [blame] | 452 | assert(!CGM.getCXXABI().NeedsVTTParameter(CurGD) && | 
| John McCall | 5c60a6f | 2010-02-18 19:59:28 +0000 | [diff] [blame] | 453 | "doing no-op VTT offset in base dtor/ctor?"); | 
| Anders Carlsson | 4d205ba | 2010-05-02 23:33:10 +0000 | [diff] [blame] | 454 | assert(!ForVirtualBase && "Can't have same class as virtual base!"); | 
| John McCall | 5c60a6f | 2010-02-18 19:59:28 +0000 | [diff] [blame] | 455 | SubVTTIndex = 0; | 
|  | 456 | } else { | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 457 | const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 458 | CharUnits BaseOffset = ForVirtualBase ? | 
|  | 459 | Layout.getVBaseClassOffset(Base) : | 
| Ken Dyck | 16ffcac | 2011-03-24 01:21:01 +0000 | [diff] [blame] | 460 | Layout.getBaseClassOffset(Base); | 
| Anders Carlsson | 859b306 | 2010-05-02 23:53:25 +0000 | [diff] [blame] | 461 |  | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 462 | SubVTTIndex = | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 463 | CGM.getVTables().getSubVTTIndex(RD, BaseSubobject(Base, BaseOffset)); | 
| John McCall | 5c60a6f | 2010-02-18 19:59:28 +0000 | [diff] [blame] | 464 | assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!"); | 
|  | 465 | } | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 466 |  | 
| Peter Collingbourne | 66f82e6 | 2013-06-28 20:45:28 +0000 | [diff] [blame] | 467 | if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) { | 
| Anders Carlsson | e36a6b3 | 2010-01-02 01:01:18 +0000 | [diff] [blame] | 468 | // A VTT parameter was passed to the constructor, use it. | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 469 | VTT = LoadCXXVTT(); | 
|  | 470 | VTT = Builder.CreateConstInBoundsGEP1_64(VTT, SubVTTIndex); | 
| Anders Carlsson | e36a6b3 | 2010-01-02 01:01:18 +0000 | [diff] [blame] | 471 | } else { | 
|  | 472 | // We're the complete constructor, so get the VTT by name. | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 473 | VTT = CGM.getVTables().GetAddrOfVTT(RD); | 
|  | 474 | VTT = Builder.CreateConstInBoundsGEP2_64(VTT, 0, SubVTTIndex); | 
| Anders Carlsson | e36a6b3 | 2010-01-02 01:01:18 +0000 | [diff] [blame] | 475 | } | 
|  | 476 |  | 
|  | 477 | return VTT; | 
|  | 478 | } | 
|  | 479 |  | 
| John McCall | 1d98756 | 2010-07-21 01:23:41 +0000 | [diff] [blame] | 480 | namespace { | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 481 | /// Call the destructor for a direct base class. | 
| David Blaikie | 7e70d68 | 2015-08-18 22:40:54 +0000 | [diff] [blame] | 482 | struct CallBaseDtor final : EHScopeStack::Cleanup { | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 483 | const CXXRecordDecl *BaseClass; | 
|  | 484 | bool BaseIsVirtual; | 
|  | 485 | CallBaseDtor(const CXXRecordDecl *Base, bool BaseIsVirtual) | 
|  | 486 | : BaseClass(Base), BaseIsVirtual(BaseIsVirtual) {} | 
| John McCall | 1d98756 | 2010-07-21 01:23:41 +0000 | [diff] [blame] | 487 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 488 | void Emit(CodeGenFunction &CGF, Flags flags) override { | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 489 | const CXXRecordDecl *DerivedClass = | 
|  | 490 | cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent(); | 
|  | 491 |  | 
|  | 492 | const CXXDestructorDecl *D = BaseClass->getDestructor(); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 493 | Address Addr = | 
|  | 494 | CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThisAddress(), | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 495 | DerivedClass, BaseClass, | 
|  | 496 | BaseIsVirtual); | 
| Douglas Gregor | 6153500 | 2013-01-31 05:50:40 +0000 | [diff] [blame] | 497 | CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual, | 
|  | 498 | /*Delegating=*/false, Addr); | 
| John McCall | 1d98756 | 2010-07-21 01:23:41 +0000 | [diff] [blame] | 499 | } | 
|  | 500 | }; | 
| John McCall | 769250e | 2010-09-17 02:31:44 +0000 | [diff] [blame] | 501 |  | 
|  | 502 | /// A visitor which checks whether an initializer uses 'this' in a | 
|  | 503 | /// way which requires the vtable to be properly set. | 
| Scott Douglass | 503fc39 | 2015-06-10 13:53:15 +0000 | [diff] [blame] | 504 | struct DynamicThisUseChecker : ConstEvaluatedExprVisitor<DynamicThisUseChecker> { | 
|  | 505 | typedef ConstEvaluatedExprVisitor<DynamicThisUseChecker> super; | 
| John McCall | 769250e | 2010-09-17 02:31:44 +0000 | [diff] [blame] | 506 |  | 
|  | 507 | bool UsesThis; | 
|  | 508 |  | 
| Scott Douglass | 503fc39 | 2015-06-10 13:53:15 +0000 | [diff] [blame] | 509 | DynamicThisUseChecker(const ASTContext &C) : super(C), UsesThis(false) {} | 
| John McCall | 769250e | 2010-09-17 02:31:44 +0000 | [diff] [blame] | 510 |  | 
|  | 511 | // Black-list all explicit and implicit references to 'this'. | 
|  | 512 | // | 
|  | 513 | // Do we need to worry about external references to 'this' derived | 
|  | 514 | // from arbitrary code?  If so, then anything which runs arbitrary | 
|  | 515 | // external code might potentially access the vtable. | 
| Scott Douglass | 503fc39 | 2015-06-10 13:53:15 +0000 | [diff] [blame] | 516 | void VisitCXXThisExpr(const CXXThisExpr *E) { UsesThis = true; } | 
| John McCall | 769250e | 2010-09-17 02:31:44 +0000 | [diff] [blame] | 517 | }; | 
| Hans Wennborg | dcfba33 | 2015-10-06 23:40:43 +0000 | [diff] [blame] | 518 | } // end anonymous namespace | 
| John McCall | 769250e | 2010-09-17 02:31:44 +0000 | [diff] [blame] | 519 |  | 
|  | 520 | static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init) { | 
|  | 521 | DynamicThisUseChecker Checker(C); | 
| Scott Douglass | 503fc39 | 2015-06-10 13:53:15 +0000 | [diff] [blame] | 522 | Checker.Visit(Init); | 
| John McCall | 769250e | 2010-09-17 02:31:44 +0000 | [diff] [blame] | 523 | return Checker.UsesThis; | 
| John McCall | 1d98756 | 2010-07-21 01:23:41 +0000 | [diff] [blame] | 524 | } | 
|  | 525 |  | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 526 | static void EmitBaseInitializer(CodeGenFunction &CGF, | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 527 | const CXXRecordDecl *ClassDecl, | 
| Alexis Hunt | 1d79265 | 2011-01-08 20:30:50 +0000 | [diff] [blame] | 528 | CXXCtorInitializer *BaseInit, | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 529 | CXXCtorType CtorType) { | 
|  | 530 | assert(BaseInit->isBaseInitializer() && | 
|  | 531 | "Must have base initializer!"); | 
|  | 532 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 533 | Address ThisPtr = CGF.LoadCXXThisAddress(); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 534 |  | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 535 | const Type *BaseType = BaseInit->getBaseClass(); | 
|  | 536 | CXXRecordDecl *BaseClassDecl = | 
|  | 537 | cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); | 
|  | 538 |  | 
| Anders Carlsson | 1c0f8bb | 2010-04-12 00:51:03 +0000 | [diff] [blame] | 539 | bool isBaseVirtual = BaseInit->isBaseVirtual(); | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 540 |  | 
|  | 541 | // The base constructor doesn't construct virtual bases. | 
|  | 542 | if (CtorType == Ctor_Base && isBaseVirtual) | 
|  | 543 | return; | 
|  | 544 |  | 
| John McCall | 769250e | 2010-09-17 02:31:44 +0000 | [diff] [blame] | 545 | // If the initializer for the base (other than the constructor | 
|  | 546 | // itself) accesses 'this' in any way, we need to initialize the | 
|  | 547 | // vtables. | 
|  | 548 | if (BaseInitializerUsesThis(CGF.getContext(), BaseInit->getInit())) | 
|  | 549 | CGF.InitializeVTablePointers(ClassDecl); | 
|  | 550 |  | 
| John McCall | 6ce7472 | 2010-02-16 04:15:37 +0000 | [diff] [blame] | 551 | // We can pretend to be a complete class because it only matters for | 
|  | 552 | // virtual bases, and we only do virtual bases for complete ctors. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 553 | Address V = | 
| Anders Carlsson | c4ba0cd | 2010-04-24 23:01:49 +0000 | [diff] [blame] | 554 | CGF.GetAddressOfDirectBaseInCompleteClass(ThisPtr, ClassDecl, | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 555 | BaseClassDecl, | 
|  | 556 | isBaseVirtual); | 
| John McCall | 8d6fc95 | 2011-08-25 20:40:09 +0000 | [diff] [blame] | 557 | AggValueSlot AggSlot = | 
| Richard Smith | e78fac5 | 2018-04-05 20:52:58 +0000 | [diff] [blame] | 558 | AggValueSlot::forAddr( | 
|  | 559 | V, Qualifiers(), | 
|  | 560 | AggValueSlot::IsDestructed, | 
|  | 561 | AggValueSlot::DoesNotNeedGCBarriers, | 
|  | 562 | AggValueSlot::IsNotAliased, | 
|  | 563 | CGF.overlapForBaseInit(ClassDecl, BaseClassDecl, isBaseVirtual)); | 
| John McCall | 7a626f6 | 2010-09-15 10:14:12 +0000 | [diff] [blame] | 564 |  | 
|  | 565 | CGF.EmitAggExpr(BaseInit->getInit(), AggSlot); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 566 |  | 
|  | 567 | if (CGF.CGM.getLangOpts().Exceptions && | 
| Anders Carlsson | 08ce5ed | 2011-02-20 00:20:27 +0000 | [diff] [blame] | 568 | !BaseClassDecl->hasTrivialDestructor()) | 
| John McCall | cda666c | 2010-07-21 07:22:38 +0000 | [diff] [blame] | 569 | CGF.EHStack.pushCleanup<CallBaseDtor>(EHCleanup, BaseClassDecl, | 
|  | 570 | isBaseVirtual); | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 571 | } | 
|  | 572 |  | 
| Richard Smith | 419bd09 | 2015-04-29 19:26:57 +0000 | [diff] [blame] | 573 | static bool isMemcpyEquivalentSpecialMember(const CXXMethodDecl *D) { | 
|  | 574 | auto *CD = dyn_cast<CXXConstructorDecl>(D); | 
|  | 575 | if (!(CD && CD->isCopyOrMoveConstructor()) && | 
|  | 576 | !D->isCopyAssignmentOperator() && !D->isMoveAssignmentOperator()) | 
|  | 577 | return false; | 
|  | 578 |  | 
|  | 579 | // We can emit a memcpy for a trivial copy or move constructor/assignment. | 
|  | 580 | if (D->isTrivial() && !D->getParent()->mayInsertExtraPadding()) | 
|  | 581 | return true; | 
|  | 582 |  | 
|  | 583 | // We *must* emit a memcpy for a defaulted union copy or move op. | 
|  | 584 | if (D->getParent()->isUnion() && D->isDefaulted()) | 
|  | 585 | return true; | 
|  | 586 |  | 
|  | 587 | return false; | 
|  | 588 | } | 
|  | 589 |  | 
| Alexey Bataev | 152c71f | 2015-07-14 07:55:48 +0000 | [diff] [blame] | 590 | static void EmitLValueForAnyFieldInitialization(CodeGenFunction &CGF, | 
|  | 591 | CXXCtorInitializer *MemberInit, | 
|  | 592 | LValue &LHS) { | 
|  | 593 | FieldDecl *Field = MemberInit->getAnyMember(); | 
|  | 594 | if (MemberInit->isIndirectMemberInitializer()) { | 
|  | 595 | // If we are initializing an anonymous union field, drill down to the field. | 
|  | 596 | IndirectFieldDecl *IndirectField = MemberInit->getIndirectMember(); | 
|  | 597 | for (const auto *I : IndirectField->chain()) | 
|  | 598 | LHS = CGF.EmitLValueForFieldInitialization(LHS, cast<FieldDecl>(I)); | 
|  | 599 | } else { | 
|  | 600 | LHS = CGF.EmitLValueForFieldInitialization(LHS, Field); | 
|  | 601 | } | 
|  | 602 | } | 
|  | 603 |  | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 604 | static void EmitMemberInitializer(CodeGenFunction &CGF, | 
|  | 605 | const CXXRecordDecl *ClassDecl, | 
| Alexis Hunt | 1d79265 | 2011-01-08 20:30:50 +0000 | [diff] [blame] | 606 | CXXCtorInitializer *MemberInit, | 
| Douglas Gregor | 94f9a48 | 2010-05-05 05:51:00 +0000 | [diff] [blame] | 607 | const CXXConstructorDecl *Constructor, | 
|  | 608 | FunctionArgList &Args) { | 
| David Blaikie | a81d410 | 2015-01-18 00:12:58 +0000 | [diff] [blame] | 609 | ApplyDebugLocation Loc(CGF, MemberInit->getSourceLocation()); | 
| Francois Pichet | d583da0 | 2010-12-04 09:14:42 +0000 | [diff] [blame] | 610 | assert(MemberInit->isAnyMemberInitializer() && | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 611 | "Must have member initializer!"); | 
| Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 612 | assert(MemberInit->getInit() && "Must have initializer!"); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 613 |  | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 614 | // non-static data member initializers. | 
| Francois Pichet | d583da0 | 2010-12-04 09:14:42 +0000 | [diff] [blame] | 615 | FieldDecl *Field = MemberInit->getAnyMember(); | 
| Eli Friedman | 6ae6302 | 2012-02-14 02:15:49 +0000 | [diff] [blame] | 616 | QualType FieldType = Field->getType(); | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 617 |  | 
|  | 618 | llvm::Value *ThisPtr = CGF.LoadCXXThis(); | 
| Eli Friedman | 7f1ff60 | 2012-04-16 03:54:45 +0000 | [diff] [blame] | 619 | QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl); | 
| Akira Hatanaka | e5dbb64 | 2018-01-27 00:34:09 +0000 | [diff] [blame] | 620 | LValue LHS; | 
|  | 621 |  | 
|  | 622 | // If a base constructor is being emitted, create an LValue that has the | 
|  | 623 | // non-virtual alignment. | 
|  | 624 | if (CGF.CurGD.getCtorType() == Ctor_Base) | 
|  | 625 | LHS = CGF.MakeNaturalAlignPointeeAddrLValue(ThisPtr, RecordTy); | 
|  | 626 | else | 
|  | 627 | LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy); | 
| Eli Friedman | 7f1ff60 | 2012-04-16 03:54:45 +0000 | [diff] [blame] | 628 |  | 
| Alexey Bataev | 152c71f | 2015-07-14 07:55:48 +0000 | [diff] [blame] | 629 | EmitLValueForAnyFieldInitialization(CGF, MemberInit, LHS); | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 630 |  | 
| Eli Friedman | 6ae6302 | 2012-02-14 02:15:49 +0000 | [diff] [blame] | 631 | // Special case: if we are in a copy or move constructor, and we are copying | 
|  | 632 | // an array of PODs or classes with trivial copy constructors, ignore the | 
|  | 633 | // AST and perform the copy we know is equivalent. | 
|  | 634 | // FIXME: This is hacky at best... if we had a bit more explicit information | 
|  | 635 | // in the AST, we could generalize it more easily. | 
|  | 636 | const ConstantArrayType *Array | 
|  | 637 | = CGF.getContext().getAsConstantArrayType(FieldType); | 
| Jordan Rose | 54533f7 | 2013-08-07 16:16:48 +0000 | [diff] [blame] | 638 | if (Array && Constructor->isDefaulted() && | 
| Eli Friedman | 6ae6302 | 2012-02-14 02:15:49 +0000 | [diff] [blame] | 639 | Constructor->isCopyOrMoveConstructor()) { | 
|  | 640 | QualType BaseElementTy = CGF.getContext().getBaseElementType(Array); | 
| Richard Smith | 993f25a | 2012-11-07 23:56:21 +0000 | [diff] [blame] | 641 | CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->getInit()); | 
| Eli Friedman | 6ae6302 | 2012-02-14 02:15:49 +0000 | [diff] [blame] | 642 | if (BaseElementTy.isPODType(CGF.getContext()) || | 
| Richard Smith | 419bd09 | 2015-04-29 19:26:57 +0000 | [diff] [blame] | 643 | (CE && isMemcpyEquivalentSpecialMember(CE->getConstructor()))) { | 
| David Majnemer | 1573d73 | 2014-10-15 04:54:54 +0000 | [diff] [blame] | 644 | unsigned SrcArgIndex = | 
|  | 645 | CGF.CGM.getCXXABI().getSrcArgforCopyCtor(Constructor, Args); | 
| Eli Friedman | 6ae6302 | 2012-02-14 02:15:49 +0000 | [diff] [blame] | 646 | llvm::Value *SrcPtr | 
|  | 647 | = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(Args[SrcArgIndex])); | 
| Eli Friedman | 7f1ff60 | 2012-04-16 03:54:45 +0000 | [diff] [blame] | 648 | LValue ThisRHSLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy); | 
|  | 649 | LValue Src = CGF.EmitLValueForFieldInitialization(ThisRHSLV, Field); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 650 |  | 
| Eli Friedman | 6ae6302 | 2012-02-14 02:15:49 +0000 | [diff] [blame] | 651 | // Copy the aggregate. | 
| Richard Smith | e78fac5 | 2018-04-05 20:52:58 +0000 | [diff] [blame] | 652 | CGF.EmitAggregateCopy(LHS, Src, FieldType, CGF.overlapForFieldInit(Field), | 
|  | 653 | LHS.isVolatileQualified()); | 
| Alexey Bataev | 5d49b83 | 2015-07-08 07:31:02 +0000 | [diff] [blame] | 654 | // Ensure that we destroy the objects if an exception is thrown later in | 
|  | 655 | // the constructor. | 
|  | 656 | QualType::DestructionKind dtorKind = FieldType.isDestructedType(); | 
|  | 657 | if (CGF.needsEHCleanup(dtorKind)) | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 658 | CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType); | 
| Eli Friedman | 6ae6302 | 2012-02-14 02:15:49 +0000 | [diff] [blame] | 659 | return; | 
|  | 660 | } | 
|  | 661 | } | 
|  | 662 |  | 
| Richard Smith | 30e304e | 2016-12-14 00:03:17 +0000 | [diff] [blame] | 663 | CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit()); | 
| Eli Friedman | 6ae6302 | 2012-02-14 02:15:49 +0000 | [diff] [blame] | 664 | } | 
|  | 665 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 666 | void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS, | 
| Richard Smith | 30e304e | 2016-12-14 00:03:17 +0000 | [diff] [blame] | 667 | Expr *Init) { | 
| Eli Friedman | 6ae6302 | 2012-02-14 02:15:49 +0000 | [diff] [blame] | 668 | QualType FieldType = Field->getType(); | 
| John McCall | 47fb950 | 2013-03-07 21:37:08 +0000 | [diff] [blame] | 669 | switch (getEvaluationKind(FieldType)) { | 
|  | 670 | case TEK_Scalar: | 
| John McCall | 31168b0 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 671 | if (LHS.isSimple()) { | 
| David Blaikie | 66e4197 | 2015-01-14 07:38:27 +0000 | [diff] [blame] | 672 | EmitExprAsInit(Init, Field, LHS, false); | 
| John McCall | 31168b0 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 673 | } else { | 
| Eli Friedman | 5f1a04f | 2012-02-14 02:31:03 +0000 | [diff] [blame] | 674 | RValue RHS = RValue::get(EmitScalarExpr(Init)); | 
|  | 675 | EmitStoreThroughLValue(RHS, LHS); | 
| John McCall | 31168b0 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 676 | } | 
| John McCall | 47fb950 | 2013-03-07 21:37:08 +0000 | [diff] [blame] | 677 | break; | 
|  | 678 | case TEK_Complex: | 
| David Blaikie | 66e4197 | 2015-01-14 07:38:27 +0000 | [diff] [blame] | 679 | EmitComplexExprIntoLValue(Init, LHS, /*isInit*/ true); | 
| John McCall | 47fb950 | 2013-03-07 21:37:08 +0000 | [diff] [blame] | 680 | break; | 
|  | 681 | case TEK_Aggregate: { | 
| Richard Smith | 30e304e | 2016-12-14 00:03:17 +0000 | [diff] [blame] | 682 | AggValueSlot Slot = | 
| Richard Smith | e78fac5 | 2018-04-05 20:52:58 +0000 | [diff] [blame] | 683 | AggValueSlot::forLValue( | 
|  | 684 | LHS, | 
|  | 685 | AggValueSlot::IsDestructed, | 
|  | 686 | AggValueSlot::DoesNotNeedGCBarriers, | 
|  | 687 | AggValueSlot::IsNotAliased, | 
| Serge Pavlov | 3760518 | 2018-07-28 15:33:03 +0000 | [diff] [blame] | 688 | overlapForFieldInit(Field), | 
|  | 689 | AggValueSlot::IsNotZeroed, | 
|  | 690 | // Checks are made by the code that calls constructor. | 
|  | 691 | AggValueSlot::IsSanitizerChecked); | 
| Richard Smith | 30e304e | 2016-12-14 00:03:17 +0000 | [diff] [blame] | 692 | EmitAggExpr(Init, Slot); | 
|  | 693 | break; | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 694 | } | 
| John McCall | 47fb950 | 2013-03-07 21:37:08 +0000 | [diff] [blame] | 695 | } | 
| John McCall | 12cc42a | 2013-02-01 05:11:40 +0000 | [diff] [blame] | 696 |  | 
|  | 697 | // Ensure that we destroy this object if an exception is thrown | 
|  | 698 | // later in the constructor. | 
|  | 699 | QualType::DestructionKind dtorKind = FieldType.isDestructedType(); | 
|  | 700 | if (needsEHCleanup(dtorKind)) | 
|  | 701 | pushEHDestroy(dtorKind, LHS.getAddress(), FieldType); | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 702 | } | 
|  | 703 |  | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 704 | /// Checks whether the given constructor is a valid subject for the | 
|  | 705 | /// complete-to-base constructor delegation optimization, i.e. | 
|  | 706 | /// emitting the complete constructor as a simple call to the base | 
|  | 707 | /// constructor. | 
| Vedant Kumar | 7f809b2 | 2017-02-24 01:15:19 +0000 | [diff] [blame] | 708 | bool CodeGenFunction::IsConstructorDelegationValid( | 
|  | 709 | const CXXConstructorDecl *Ctor) { | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 710 |  | 
|  | 711 | // Currently we disable the optimization for classes with virtual | 
|  | 712 | // bases because (1) the addresses of parameter variables need to be | 
|  | 713 | // consistent across all initializers but (2) the delegate function | 
|  | 714 | // call necessarily creates a second copy of the parameter variable. | 
|  | 715 | // | 
|  | 716 | // The limiting example (purely theoretical AFAIK): | 
|  | 717 | //   struct A { A(int &c) { c++; } }; | 
|  | 718 | //   struct B : virtual A { | 
|  | 719 | //     B(int count) : A(count) { printf("%d\n", count); } | 
|  | 720 | //   }; | 
|  | 721 | // ...although even this example could in principle be emitted as a | 
|  | 722 | // delegation since the address of the parameter doesn't escape. | 
|  | 723 | if (Ctor->getParent()->getNumVBases()) { | 
|  | 724 | // TODO: white-list trivial vbase initializers.  This case wouldn't | 
|  | 725 | // be subject to the restrictions below. | 
|  | 726 |  | 
|  | 727 | // TODO: white-list cases where: | 
|  | 728 | //  - there are no non-reference parameters to the constructor | 
|  | 729 | //  - the initializers don't access any non-reference parameters | 
|  | 730 | //  - the initializers don't take the address of non-reference | 
|  | 731 | //    parameters | 
|  | 732 | //  - etc. | 
|  | 733 | // If we ever add any of the above cases, remember that: | 
|  | 734 | //  - function-try-blocks will always blacklist this optimization | 
|  | 735 | //  - we need to perform the constructor prologue and cleanup in | 
|  | 736 | //    EmitConstructorBody. | 
|  | 737 |  | 
|  | 738 | return false; | 
|  | 739 | } | 
|  | 740 |  | 
|  | 741 | // We also disable the optimization for variadic functions because | 
|  | 742 | // it's impossible to "re-pass" varargs. | 
|  | 743 | if (Ctor->getType()->getAs<FunctionProtoType>()->isVariadic()) | 
|  | 744 | return false; | 
|  | 745 |  | 
| Alexis Hunt | 61bc173 | 2011-05-01 07:04:31 +0000 | [diff] [blame] | 746 | // FIXME: Decide if we can do a delegation of a delegating constructor. | 
|  | 747 | if (Ctor->isDelegatingConstructor()) | 
|  | 748 | return false; | 
|  | 749 |  | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 750 | return true; | 
|  | 751 | } | 
|  | 752 |  | 
| Kostya Serebryany | 293dc9b | 2014-10-16 20:54:52 +0000 | [diff] [blame] | 753 | // Emit code in ctor (Prologue==true) or dtor (Prologue==false) | 
|  | 754 | // to poison the extra field paddings inserted under | 
|  | 755 | // -fsanitize-address-field-padding=1|2. | 
|  | 756 | void CodeGenFunction::EmitAsanPrologueOrEpilogue(bool Prologue) { | 
|  | 757 | ASTContext &Context = getContext(); | 
|  | 758 | const CXXRecordDecl *ClassDecl = | 
|  | 759 | Prologue ? cast<CXXConstructorDecl>(CurGD.getDecl())->getParent() | 
|  | 760 | : cast<CXXDestructorDecl>(CurGD.getDecl())->getParent(); | 
|  | 761 | if (!ClassDecl->mayInsertExtraPadding()) return; | 
|  | 762 |  | 
|  | 763 | struct SizeAndOffset { | 
|  | 764 | uint64_t Size; | 
|  | 765 | uint64_t Offset; | 
|  | 766 | }; | 
|  | 767 |  | 
|  | 768 | unsigned PtrSize = CGM.getDataLayout().getPointerSizeInBits(); | 
|  | 769 | const ASTRecordLayout &Info = Context.getASTRecordLayout(ClassDecl); | 
|  | 770 |  | 
|  | 771 | // Populate sizes and offsets of fields. | 
|  | 772 | SmallVector<SizeAndOffset, 16> SSV(Info.getFieldCount()); | 
|  | 773 | for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i) | 
|  | 774 | SSV[i].Offset = | 
|  | 775 | Context.toCharUnitsFromBits(Info.getFieldOffset(i)).getQuantity(); | 
|  | 776 |  | 
|  | 777 | size_t NumFields = 0; | 
|  | 778 | for (const auto *Field : ClassDecl->fields()) { | 
|  | 779 | const FieldDecl *D = Field; | 
|  | 780 | std::pair<CharUnits, CharUnits> FieldInfo = | 
|  | 781 | Context.getTypeInfoInChars(D->getType()); | 
|  | 782 | CharUnits FieldSize = FieldInfo.first; | 
|  | 783 | assert(NumFields < SSV.size()); | 
|  | 784 | SSV[NumFields].Size = D->isBitField() ? 0 : FieldSize.getQuantity(); | 
|  | 785 | NumFields++; | 
|  | 786 | } | 
|  | 787 | assert(NumFields == SSV.size()); | 
|  | 788 | if (SSV.size() <= 1) return; | 
|  | 789 |  | 
|  | 790 | // We will insert calls to __asan_* run-time functions. | 
|  | 791 | // LLVM AddressSanitizer pass may decide to inline them later. | 
|  | 792 | llvm::Type *Args[2] = {IntPtrTy, IntPtrTy}; | 
|  | 793 | llvm::FunctionType *FTy = | 
|  | 794 | llvm::FunctionType::get(CGM.VoidTy, Args, false); | 
|  | 795 | llvm::Constant *F = CGM.CreateRuntimeFunction( | 
|  | 796 | FTy, Prologue ? "__asan_poison_intra_object_redzone" | 
|  | 797 | : "__asan_unpoison_intra_object_redzone"); | 
|  | 798 |  | 
|  | 799 | llvm::Value *ThisPtr = LoadCXXThis(); | 
|  | 800 | ThisPtr = Builder.CreatePtrToInt(ThisPtr, IntPtrTy); | 
| Kostya Serebryany | 6444921 | 2014-10-17 21:02:13 +0000 | [diff] [blame] | 801 | uint64_t TypeSize = Info.getNonVirtualSize().getQuantity(); | 
| Kostya Serebryany | 293dc9b | 2014-10-16 20:54:52 +0000 | [diff] [blame] | 802 | // For each field check if it has sufficient padding, | 
|  | 803 | // if so (un)poison it with a call. | 
|  | 804 | for (size_t i = 0; i < SSV.size(); i++) { | 
|  | 805 | uint64_t AsanAlignment = 8; | 
|  | 806 | uint64_t NextField = i == SSV.size() - 1 ? TypeSize : SSV[i + 1].Offset; | 
|  | 807 | uint64_t PoisonSize = NextField - SSV[i].Offset - SSV[i].Size; | 
|  | 808 | uint64_t EndOffset = SSV[i].Offset + SSV[i].Size; | 
|  | 809 | if (PoisonSize < AsanAlignment || !SSV[i].Size || | 
|  | 810 | (NextField % AsanAlignment) != 0) | 
|  | 811 | continue; | 
| David Blaikie | 43f9bb7 | 2015-05-18 22:14:03 +0000 | [diff] [blame] | 812 | Builder.CreateCall( | 
|  | 813 | F, {Builder.CreateAdd(ThisPtr, Builder.getIntN(PtrSize, EndOffset)), | 
|  | 814 | Builder.getIntN(PtrSize, PoisonSize)}); | 
| Kostya Serebryany | 293dc9b | 2014-10-16 20:54:52 +0000 | [diff] [blame] | 815 | } | 
|  | 816 | } | 
|  | 817 |  | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 818 | /// EmitConstructorBody - Emits the body of the current constructor. | 
|  | 819 | void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) { | 
| Kostya Serebryany | 293dc9b | 2014-10-16 20:54:52 +0000 | [diff] [blame] | 820 | EmitAsanPrologueOrEpilogue(true); | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 821 | const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(CurGD.getDecl()); | 
|  | 822 | CXXCtorType CtorType = CurGD.getCtorType(); | 
|  | 823 |  | 
| Reid Kleckner | 340ad86 | 2014-01-13 22:57:31 +0000 | [diff] [blame] | 824 | assert((CGM.getTarget().getCXXABI().hasConstructorVariants() || | 
|  | 825 | CtorType == Ctor_Complete) && | 
|  | 826 | "can only generate complete ctor for this ABI"); | 
|  | 827 |  | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 828 | // Before we go any further, try the complete->base constructor | 
|  | 829 | // delegation optimization. | 
| Timur Iskhodzhanov | f32a377 | 2012-04-20 08:05:00 +0000 | [diff] [blame] | 830 | if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor) && | 
| John McCall | c8e0170 | 2013-04-16 22:48:15 +0000 | [diff] [blame] | 831 | CGM.getTarget().getCXXABI().hasConstructorVariants()) { | 
| Stephen Kelly | 1c301dc | 2018-08-09 21:09:38 +0000 | [diff] [blame] | 832 | EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args, Ctor->getEndLoc()); | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 833 | return; | 
|  | 834 | } | 
|  | 835 |  | 
| Hans Wennborg | dcfba33 | 2015-10-06 23:40:43 +0000 | [diff] [blame] | 836 | const FunctionDecl *Definition = nullptr; | 
| Richard Smith | 46bb581 | 2014-08-01 01:56:39 +0000 | [diff] [blame] | 837 | Stmt *Body = Ctor->getBody(Definition); | 
|  | 838 | assert(Definition == Ctor && "emitting wrong constructor body"); | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 839 |  | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 840 | // Enter the function-try-block before the constructor prologue if | 
|  | 841 | // applicable. | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 842 | bool IsTryBody = (Body && isa<CXXTryStmt>(Body)); | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 843 | if (IsTryBody) | 
| John McCall | b609d3f | 2010-07-07 06:56:46 +0000 | [diff] [blame] | 844 | EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true); | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 845 |  | 
| Justin Bogner | 66242d6 | 2015-04-23 23:06:47 +0000 | [diff] [blame] | 846 | incrementProfileCounter(Body); | 
| Justin Bogner | 81c22c2 | 2014-01-23 02:54:27 +0000 | [diff] [blame] | 847 |  | 
| Richard Smith | cc1b96d | 2013-06-12 22:31:48 +0000 | [diff] [blame] | 848 | RunCleanupsScope RunCleanups(*this); | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 849 |  | 
| John McCall | 8831303 | 2012-03-30 04:25:03 +0000 | [diff] [blame] | 850 | // TODO: in restricted cases, we can emit the vbase initializers of | 
|  | 851 | // a complete ctor and then delegate to the base ctor. | 
|  | 852 |  | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 853 | // Emit the constructor prologue, i.e. the base and member | 
|  | 854 | // initializers. | 
| Douglas Gregor | 94f9a48 | 2010-05-05 05:51:00 +0000 | [diff] [blame] | 855 | EmitCtorPrologue(Ctor, CtorType, Args); | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 856 |  | 
|  | 857 | // Emit the body of the statement. | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 858 | if (IsTryBody) | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 859 | EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock()); | 
|  | 860 | else if (Body) | 
|  | 861 | EmitStmt(Body); | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 862 |  | 
|  | 863 | // Emit any cleanup blocks associated with the member or base | 
|  | 864 | // initializers, which includes (along the exceptional path) the | 
|  | 865 | // destructors for those members and bases that were fully | 
|  | 866 | // constructed. | 
| Richard Smith | cc1b96d | 2013-06-12 22:31:48 +0000 | [diff] [blame] | 867 | RunCleanups.ForceCleanup(); | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 868 |  | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 869 | if (IsTryBody) | 
| John McCall | b609d3f | 2010-07-07 06:56:46 +0000 | [diff] [blame] | 870 | ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true); | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 871 | } | 
|  | 872 |  | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 873 | namespace { | 
| Nick Lewycky | 8b4e379 | 2013-09-11 02:03:20 +0000 | [diff] [blame] | 874 | /// RAII object to indicate that codegen is copying the value representation | 
|  | 875 | /// instead of the object representation. Useful when copying a struct or | 
|  | 876 | /// class which has uninitialized members and we're only performing | 
|  | 877 | /// lvalue-to-rvalue conversion on the object but not its members. | 
|  | 878 | class CopyingValueRepresentation { | 
|  | 879 | public: | 
|  | 880 | explicit CopyingValueRepresentation(CodeGenFunction &CGF) | 
| Alexey Samsonov | 035462c | 2014-10-30 19:33:44 +0000 | [diff] [blame] | 881 | : CGF(CGF), OldSanOpts(CGF.SanOpts) { | 
| Alexey Samsonov | edf99a9 | 2014-11-07 22:29:38 +0000 | [diff] [blame] | 882 | CGF.SanOpts.set(SanitizerKind::Bool, false); | 
|  | 883 | CGF.SanOpts.set(SanitizerKind::Enum, false); | 
| Nick Lewycky | 8b4e379 | 2013-09-11 02:03:20 +0000 | [diff] [blame] | 884 | } | 
|  | 885 | ~CopyingValueRepresentation() { | 
|  | 886 | CGF.SanOpts = OldSanOpts; | 
|  | 887 | } | 
|  | 888 | private: | 
|  | 889 | CodeGenFunction &CGF; | 
| Alexey Samsonov | a041610 | 2014-11-11 01:26:14 +0000 | [diff] [blame] | 890 | SanitizerSet OldSanOpts; | 
| Nick Lewycky | 8b4e379 | 2013-09-11 02:03:20 +0000 | [diff] [blame] | 891 | }; | 
| Eugene Zelenko | 0a4f3f4 | 2016-02-10 19:11:58 +0000 | [diff] [blame] | 892 | } // end anonymous namespace | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 893 |  | 
| Nick Lewycky | 8b4e379 | 2013-09-11 02:03:20 +0000 | [diff] [blame] | 894 | namespace { | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 895 | class FieldMemcpyizer { | 
|  | 896 | public: | 
|  | 897 | FieldMemcpyizer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl, | 
|  | 898 | const VarDecl *SrcRec) | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 899 | : CGF(CGF), ClassDecl(ClassDecl), SrcRec(SrcRec), | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 900 | RecLayout(CGF.getContext().getASTRecordLayout(ClassDecl)), | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 901 | FirstField(nullptr), LastField(nullptr), FirstFieldOffset(0), | 
|  | 902 | LastFieldOffset(0), LastAddedFieldIndex(0) {} | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 903 |  | 
| Kostya Serebryany | 293dc9b | 2014-10-16 20:54:52 +0000 | [diff] [blame] | 904 | bool isMemcpyableField(FieldDecl *F) const { | 
|  | 905 | // Never memcpy fields when we are adding poisoned paddings. | 
| Alexey Samsonov | a041610 | 2014-11-11 01:26:14 +0000 | [diff] [blame] | 906 | if (CGF.getContext().getLangOpts().SanitizeAddressFieldPadding) | 
| Kostya Serebryany | 293dc9b | 2014-10-16 20:54:52 +0000 | [diff] [blame] | 907 | return false; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 908 | Qualifiers Qual = F->getType().getQualifiers(); | 
|  | 909 | if (Qual.hasVolatile() || Qual.hasObjCLifetime()) | 
|  | 910 | return false; | 
|  | 911 | return true; | 
|  | 912 | } | 
|  | 913 |  | 
|  | 914 | void addMemcpyableField(FieldDecl *F) { | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 915 | if (!FirstField) | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 916 | addInitialField(F); | 
|  | 917 | else | 
|  | 918 | addNextField(F); | 
|  | 919 | } | 
|  | 920 |  | 
| David Majnemer | a586eb2 | 2014-10-10 18:57:10 +0000 | [diff] [blame] | 921 | CharUnits getMemcpySize(uint64_t FirstByteOffset) const { | 
| Richard Smith | e78fac5 | 2018-04-05 20:52:58 +0000 | [diff] [blame] | 922 | ASTContext &Ctx = CGF.getContext(); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 923 | unsigned LastFieldSize = | 
| Richard Smith | e78fac5 | 2018-04-05 20:52:58 +0000 | [diff] [blame] | 924 | LastField->isBitField() | 
|  | 925 | ? LastField->getBitWidthValue(Ctx) | 
|  | 926 | : Ctx.toBits( | 
|  | 927 | Ctx.getTypeInfoDataSizeInChars(LastField->getType()).first); | 
|  | 928 | uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize - | 
|  | 929 | FirstByteOffset + Ctx.getCharWidth() - 1; | 
|  | 930 | CharUnits MemcpySize = Ctx.toCharUnitsFromBits(MemcpySizeBits); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 931 | return MemcpySize; | 
|  | 932 | } | 
|  | 933 |  | 
|  | 934 | void emitMemcpy() { | 
|  | 935 | // Give the subclass a chance to bail out if it feels the memcpy isn't | 
|  | 936 | // worth it (e.g. Hasn't aggregated enough data). | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 937 | if (!FirstField) { | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 938 | return; | 
|  | 939 | } | 
|  | 940 |  | 
| David Majnemer | a586eb2 | 2014-10-10 18:57:10 +0000 | [diff] [blame] | 941 | uint64_t FirstByteOffset; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 942 | if (FirstField->isBitField()) { | 
|  | 943 | const CGRecordLayout &RL = | 
|  | 944 | CGF.getTypes().getCGRecordLayout(FirstField->getParent()); | 
|  | 945 | const CGBitFieldInfo &BFInfo = RL.getBitFieldInfo(FirstField); | 
| David Majnemer | a586eb2 | 2014-10-10 18:57:10 +0000 | [diff] [blame] | 946 | // FirstFieldOffset is not appropriate for bitfields, | 
| Ulrich Weigand | 73263d7 | 2015-07-13 11:52:14 +0000 | [diff] [blame] | 947 | // we need to use the storage offset instead. | 
| Ulrich Weigand | 03ce2a1 | 2015-07-10 17:30:00 +0000 | [diff] [blame] | 948 | FirstByteOffset = CGF.getContext().toBits(BFInfo.StorageOffset); | 
| Lang Hames | 1694e0d | 2013-02-27 04:14:49 +0000 | [diff] [blame] | 949 | } else { | 
| David Majnemer | a586eb2 | 2014-10-10 18:57:10 +0000 | [diff] [blame] | 950 | FirstByteOffset = FirstFieldOffset; | 
| Lang Hames | 1694e0d | 2013-02-27 04:14:49 +0000 | [diff] [blame] | 951 | } | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 952 |  | 
| David Majnemer | a586eb2 | 2014-10-10 18:57:10 +0000 | [diff] [blame] | 953 | CharUnits MemcpySize = getMemcpySize(FirstByteOffset); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 954 | QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 955 | Address ThisPtr = CGF.LoadCXXThisAddress(); | 
|  | 956 | LValue DestLV = CGF.MakeAddrLValue(ThisPtr, RecordTy); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 957 | LValue Dest = CGF.EmitLValueForFieldInitialization(DestLV, FirstField); | 
|  | 958 | llvm::Value *SrcPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(SrcRec)); | 
|  | 959 | LValue SrcLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy); | 
|  | 960 | LValue Src = CGF.EmitLValueForFieldInitialization(SrcLV, FirstField); | 
|  | 961 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 962 | emitMemcpyIR(Dest.isBitField() ? Dest.getBitFieldAddress() : Dest.getAddress(), | 
|  | 963 | Src.isBitField() ? Src.getBitFieldAddress() : Src.getAddress(), | 
|  | 964 | MemcpySize); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 965 | reset(); | 
|  | 966 | } | 
|  | 967 |  | 
|  | 968 | void reset() { | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 969 | FirstField = nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 970 | } | 
|  | 971 |  | 
|  | 972 | protected: | 
|  | 973 | CodeGenFunction &CGF; | 
|  | 974 | const CXXRecordDecl *ClassDecl; | 
|  | 975 |  | 
|  | 976 | private: | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 977 | void emitMemcpyIR(Address DestPtr, Address SrcPtr, CharUnits Size) { | 
|  | 978 | llvm::PointerType *DPT = DestPtr.getType(); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 979 | llvm::Type *DBP = | 
|  | 980 | llvm::Type::getInt8PtrTy(CGF.getLLVMContext(), DPT->getAddressSpace()); | 
|  | 981 | DestPtr = CGF.Builder.CreateBitCast(DestPtr, DBP); | 
|  | 982 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 983 | llvm::PointerType *SPT = SrcPtr.getType(); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 984 | llvm::Type *SBP = | 
|  | 985 | llvm::Type::getInt8PtrTy(CGF.getLLVMContext(), SPT->getAddressSpace()); | 
|  | 986 | SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, SBP); | 
|  | 987 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 988 | CGF.Builder.CreateMemCpy(DestPtr, SrcPtr, Size.getQuantity()); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 989 | } | 
|  | 990 |  | 
|  | 991 | void addInitialField(FieldDecl *F) { | 
| Eugene Zelenko | 0a4f3f4 | 2016-02-10 19:11:58 +0000 | [diff] [blame] | 992 | FirstField = F; | 
|  | 993 | LastField = F; | 
|  | 994 | FirstFieldOffset = RecLayout.getFieldOffset(F->getFieldIndex()); | 
|  | 995 | LastFieldOffset = FirstFieldOffset; | 
|  | 996 | LastAddedFieldIndex = F->getFieldIndex(); | 
|  | 997 | } | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 998 |  | 
|  | 999 | void addNextField(FieldDecl *F) { | 
| John McCall | 6054d5a | 2013-05-07 05:20:46 +0000 | [diff] [blame] | 1000 | // For the most part, the following invariant will hold: | 
|  | 1001 | //   F->getFieldIndex() == LastAddedFieldIndex + 1 | 
|  | 1002 | // The one exception is that Sema won't add a copy-initializer for an | 
|  | 1003 | // unnamed bitfield, which will show up here as a gap in the sequence. | 
|  | 1004 | assert(F->getFieldIndex() >= LastAddedFieldIndex + 1 && | 
|  | 1005 | "Cannot aggregate fields out of order."); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1006 | LastAddedFieldIndex = F->getFieldIndex(); | 
|  | 1007 |  | 
|  | 1008 | // The 'first' and 'last' fields are chosen by offset, rather than field | 
|  | 1009 | // index. This allows the code to support bitfields, as well as regular | 
|  | 1010 | // fields. | 
|  | 1011 | uint64_t FOffset = RecLayout.getFieldOffset(F->getFieldIndex()); | 
|  | 1012 | if (FOffset < FirstFieldOffset) { | 
|  | 1013 | FirstField = F; | 
|  | 1014 | FirstFieldOffset = FOffset; | 
|  | 1015 | } else if (FOffset > LastFieldOffset) { | 
|  | 1016 | LastField = F; | 
|  | 1017 | LastFieldOffset = FOffset; | 
|  | 1018 | } | 
|  | 1019 | } | 
|  | 1020 |  | 
|  | 1021 | const VarDecl *SrcRec; | 
|  | 1022 | const ASTRecordLayout &RecLayout; | 
|  | 1023 | FieldDecl *FirstField; | 
|  | 1024 | FieldDecl *LastField; | 
|  | 1025 | uint64_t FirstFieldOffset, LastFieldOffset; | 
|  | 1026 | unsigned LastAddedFieldIndex; | 
|  | 1027 | }; | 
|  | 1028 |  | 
|  | 1029 | class ConstructorMemcpyizer : public FieldMemcpyizer { | 
|  | 1030 | private: | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1031 | /// Get source argument for copy constructor. Returns null if not a copy | 
| David Majnemer | 196ac33 | 2014-09-11 23:05:02 +0000 | [diff] [blame] | 1032 | /// constructor. | 
|  | 1033 | static const VarDecl *getTrivialCopySource(CodeGenFunction &CGF, | 
|  | 1034 | const CXXConstructorDecl *CD, | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1035 | FunctionArgList &Args) { | 
| Jordan Rose | 54533f7 | 2013-08-07 16:16:48 +0000 | [diff] [blame] | 1036 | if (CD->isCopyOrMoveConstructor() && CD->isDefaulted()) | 
| David Majnemer | 196ac33 | 2014-09-11 23:05:02 +0000 | [diff] [blame] | 1037 | return Args[CGF.CGM.getCXXABI().getSrcArgforCopyCtor(CD, Args)]; | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1038 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1039 | } | 
|  | 1040 |  | 
|  | 1041 | // Returns true if a CXXCtorInitializer represents a member initialization | 
|  | 1042 | // that can be rolled into a memcpy. | 
|  | 1043 | bool isMemberInitMemcpyable(CXXCtorInitializer *MemberInit) const { | 
|  | 1044 | if (!MemcpyableCtor) | 
|  | 1045 | return false; | 
|  | 1046 | FieldDecl *Field = MemberInit->getMember(); | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1047 | assert(Field && "No field for member init."); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1048 | QualType FieldType = Field->getType(); | 
|  | 1049 | CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->getInit()); | 
|  | 1050 |  | 
| Richard Smith | 419bd09 | 2015-04-29 19:26:57 +0000 | [diff] [blame] | 1051 | // Bail out on non-memcpyable, not-trivially-copyable members. | 
|  | 1052 | if (!(CE && isMemcpyEquivalentSpecialMember(CE->getConstructor())) && | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1053 | !(FieldType.isTriviallyCopyableType(CGF.getContext()) || | 
|  | 1054 | FieldType->isReferenceType())) | 
|  | 1055 | return false; | 
|  | 1056 |  | 
|  | 1057 | // Bail out on volatile fields. | 
|  | 1058 | if (!isMemcpyableField(Field)) | 
|  | 1059 | return false; | 
|  | 1060 |  | 
|  | 1061 | // Otherwise we're good. | 
|  | 1062 | return true; | 
|  | 1063 | } | 
|  | 1064 |  | 
|  | 1065 | public: | 
|  | 1066 | ConstructorMemcpyizer(CodeGenFunction &CGF, const CXXConstructorDecl *CD, | 
|  | 1067 | FunctionArgList &Args) | 
| David Majnemer | 196ac33 | 2014-09-11 23:05:02 +0000 | [diff] [blame] | 1068 | : FieldMemcpyizer(CGF, CD->getParent(), getTrivialCopySource(CGF, CD, Args)), | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1069 | ConstructorDecl(CD), | 
| Jordan Rose | 54533f7 | 2013-08-07 16:16:48 +0000 | [diff] [blame] | 1070 | MemcpyableCtor(CD->isDefaulted() && | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1071 | CD->isCopyOrMoveConstructor() && | 
|  | 1072 | CGF.getLangOpts().getGC() == LangOptions::NonGC), | 
|  | 1073 | Args(Args) { } | 
|  | 1074 |  | 
|  | 1075 | void addMemberInitializer(CXXCtorInitializer *MemberInit) { | 
|  | 1076 | if (isMemberInitMemcpyable(MemberInit)) { | 
|  | 1077 | AggregatedInits.push_back(MemberInit); | 
|  | 1078 | addMemcpyableField(MemberInit->getMember()); | 
|  | 1079 | } else { | 
|  | 1080 | emitAggregatedInits(); | 
|  | 1081 | EmitMemberInitializer(CGF, ConstructorDecl->getParent(), MemberInit, | 
|  | 1082 | ConstructorDecl, Args); | 
|  | 1083 | } | 
|  | 1084 | } | 
|  | 1085 |  | 
|  | 1086 | void emitAggregatedInits() { | 
|  | 1087 | if (AggregatedInits.size() <= 1) { | 
|  | 1088 | // This memcpy is too small to be worthwhile. Fall back on default | 
|  | 1089 | // codegen. | 
| Nick Lewycky | 8b4e379 | 2013-09-11 02:03:20 +0000 | [diff] [blame] | 1090 | if (!AggregatedInits.empty()) { | 
|  | 1091 | CopyingValueRepresentation CVR(CGF); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1092 | EmitMemberInitializer(CGF, ConstructorDecl->getParent(), | 
| Nick Lewycky | 8b4e379 | 2013-09-11 02:03:20 +0000 | [diff] [blame] | 1093 | AggregatedInits[0], ConstructorDecl, Args); | 
| Alexey Bataev | 152c71f | 2015-07-14 07:55:48 +0000 | [diff] [blame] | 1094 | AggregatedInits.clear(); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1095 | } | 
|  | 1096 | reset(); | 
|  | 1097 | return; | 
|  | 1098 | } | 
|  | 1099 |  | 
|  | 1100 | pushEHDestructors(); | 
|  | 1101 | emitMemcpy(); | 
|  | 1102 | AggregatedInits.clear(); | 
|  | 1103 | } | 
|  | 1104 |  | 
|  | 1105 | void pushEHDestructors() { | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1106 | Address ThisPtr = CGF.LoadCXXThisAddress(); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1107 | QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1108 | LValue LHS = CGF.MakeAddrLValue(ThisPtr, RecordTy); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1109 |  | 
|  | 1110 | for (unsigned i = 0; i < AggregatedInits.size(); ++i) { | 
| Alexey Bataev | 152c71f | 2015-07-14 07:55:48 +0000 | [diff] [blame] | 1111 | CXXCtorInitializer *MemberInit = AggregatedInits[i]; | 
|  | 1112 | QualType FieldType = MemberInit->getAnyMember()->getType(); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1113 | QualType::DestructionKind dtorKind = FieldType.isDestructedType(); | 
| Alexey Bataev | 152c71f | 2015-07-14 07:55:48 +0000 | [diff] [blame] | 1114 | if (!CGF.needsEHCleanup(dtorKind)) | 
|  | 1115 | continue; | 
|  | 1116 | LValue FieldLHS = LHS; | 
|  | 1117 | EmitLValueForAnyFieldInitialization(CGF, MemberInit, FieldLHS); | 
|  | 1118 | CGF.pushEHDestroy(dtorKind, FieldLHS.getAddress(), FieldType); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1119 | } | 
|  | 1120 | } | 
|  | 1121 |  | 
|  | 1122 | void finish() { | 
|  | 1123 | emitAggregatedInits(); | 
|  | 1124 | } | 
|  | 1125 |  | 
|  | 1126 | private: | 
|  | 1127 | const CXXConstructorDecl *ConstructorDecl; | 
|  | 1128 | bool MemcpyableCtor; | 
|  | 1129 | FunctionArgList &Args; | 
|  | 1130 | SmallVector<CXXCtorInitializer*, 16> AggregatedInits; | 
|  | 1131 | }; | 
|  | 1132 |  | 
|  | 1133 | class AssignmentMemcpyizer : public FieldMemcpyizer { | 
|  | 1134 | private: | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1135 | // Returns the memcpyable field copied by the given statement, if one | 
| Nick Lewycky | 8b4e379 | 2013-09-11 02:03:20 +0000 | [diff] [blame] | 1136 | // exists. Otherwise returns null. | 
|  | 1137 | FieldDecl *getMemcpyableField(Stmt *S) { | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1138 | if (!AssignmentsMemcpyable) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1139 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1140 | if (BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) { | 
|  | 1141 | // Recognise trivial assignments. | 
|  | 1142 | if (BO->getOpcode() != BO_Assign) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1143 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1144 | MemberExpr *ME = dyn_cast<MemberExpr>(BO->getLHS()); | 
|  | 1145 | if (!ME) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1146 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1147 | FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl()); | 
|  | 1148 | if (!Field || !isMemcpyableField(Field)) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1149 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1150 | Stmt *RHS = BO->getRHS(); | 
|  | 1151 | if (ImplicitCastExpr *EC = dyn_cast<ImplicitCastExpr>(RHS)) | 
|  | 1152 | RHS = EC->getSubExpr(); | 
|  | 1153 | if (!RHS) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1154 | return nullptr; | 
| Warren Ristow | 8d17b40 | 2017-02-02 17:53:34 +0000 | [diff] [blame] | 1155 | if (MemberExpr *ME2 = dyn_cast<MemberExpr>(RHS)) { | 
|  | 1156 | if (ME2->getMemberDecl() == Field) | 
|  | 1157 | return Field; | 
|  | 1158 | } | 
|  | 1159 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1160 | } else if (CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(S)) { | 
|  | 1161 | CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MCE->getCalleeDecl()); | 
| Richard Smith | 419bd09 | 2015-04-29 19:26:57 +0000 | [diff] [blame] | 1162 | if (!(MD && isMemcpyEquivalentSpecialMember(MD))) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1163 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1164 | MemberExpr *IOA = dyn_cast<MemberExpr>(MCE->getImplicitObjectArgument()); | 
|  | 1165 | if (!IOA) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1166 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1167 | FieldDecl *Field = dyn_cast<FieldDecl>(IOA->getMemberDecl()); | 
|  | 1168 | if (!Field || !isMemcpyableField(Field)) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1169 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1170 | MemberExpr *Arg0 = dyn_cast<MemberExpr>(MCE->getArg(0)); | 
|  | 1171 | if (!Arg0 || Field != dyn_cast<FieldDecl>(Arg0->getMemberDecl())) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1172 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1173 | return Field; | 
|  | 1174 | } else if (CallExpr *CE = dyn_cast<CallExpr>(S)) { | 
|  | 1175 | FunctionDecl *FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl()); | 
|  | 1176 | if (!FD || FD->getBuiltinID() != Builtin::BI__builtin_memcpy) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1177 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1178 | Expr *DstPtr = CE->getArg(0); | 
|  | 1179 | if (ImplicitCastExpr *DC = dyn_cast<ImplicitCastExpr>(DstPtr)) | 
|  | 1180 | DstPtr = DC->getSubExpr(); | 
|  | 1181 | UnaryOperator *DUO = dyn_cast<UnaryOperator>(DstPtr); | 
|  | 1182 | if (!DUO || DUO->getOpcode() != UO_AddrOf) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1183 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1184 | MemberExpr *ME = dyn_cast<MemberExpr>(DUO->getSubExpr()); | 
|  | 1185 | if (!ME) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1186 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1187 | FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl()); | 
|  | 1188 | if (!Field || !isMemcpyableField(Field)) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1189 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1190 | Expr *SrcPtr = CE->getArg(1); | 
|  | 1191 | if (ImplicitCastExpr *SC = dyn_cast<ImplicitCastExpr>(SrcPtr)) | 
|  | 1192 | SrcPtr = SC->getSubExpr(); | 
|  | 1193 | UnaryOperator *SUO = dyn_cast<UnaryOperator>(SrcPtr); | 
|  | 1194 | if (!SUO || SUO->getOpcode() != UO_AddrOf) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1195 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1196 | MemberExpr *ME2 = dyn_cast<MemberExpr>(SUO->getSubExpr()); | 
|  | 1197 | if (!ME2 || Field != dyn_cast<FieldDecl>(ME2->getMemberDecl())) | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1198 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1199 | return Field; | 
|  | 1200 | } | 
|  | 1201 |  | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1202 | return nullptr; | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1203 | } | 
|  | 1204 |  | 
|  | 1205 | bool AssignmentsMemcpyable; | 
|  | 1206 | SmallVector<Stmt*, 16> AggregatedStmts; | 
|  | 1207 |  | 
|  | 1208 | public: | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1209 | AssignmentMemcpyizer(CodeGenFunction &CGF, const CXXMethodDecl *AD, | 
|  | 1210 | FunctionArgList &Args) | 
|  | 1211 | : FieldMemcpyizer(CGF, AD->getParent(), Args[Args.size() - 1]), | 
|  | 1212 | AssignmentsMemcpyable(CGF.getLangOpts().getGC() == LangOptions::NonGC) { | 
|  | 1213 | assert(Args.size() == 2); | 
|  | 1214 | } | 
|  | 1215 |  | 
|  | 1216 | void emitAssignment(Stmt *S) { | 
|  | 1217 | FieldDecl *F = getMemcpyableField(S); | 
|  | 1218 | if (F) { | 
|  | 1219 | addMemcpyableField(F); | 
|  | 1220 | AggregatedStmts.push_back(S); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1221 | } else { | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1222 | emitAggregatedStmts(); | 
|  | 1223 | CGF.EmitStmt(S); | 
|  | 1224 | } | 
|  | 1225 | } | 
|  | 1226 |  | 
|  | 1227 | void emitAggregatedStmts() { | 
|  | 1228 | if (AggregatedStmts.size() <= 1) { | 
| Nick Lewycky | 8b4e379 | 2013-09-11 02:03:20 +0000 | [diff] [blame] | 1229 | if (!AggregatedStmts.empty()) { | 
|  | 1230 | CopyingValueRepresentation CVR(CGF); | 
|  | 1231 | CGF.EmitStmt(AggregatedStmts[0]); | 
|  | 1232 | } | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1233 | reset(); | 
|  | 1234 | } | 
|  | 1235 |  | 
|  | 1236 | emitMemcpy(); | 
|  | 1237 | AggregatedStmts.clear(); | 
|  | 1238 | } | 
|  | 1239 |  | 
|  | 1240 | void finish() { | 
|  | 1241 | emitAggregatedStmts(); | 
|  | 1242 | } | 
|  | 1243 | }; | 
| Hans Wennborg | dcfba33 | 2015-10-06 23:40:43 +0000 | [diff] [blame] | 1244 | } // end anonymous namespace | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1245 |  | 
| Piotr Padlewski | 338c9d0 | 2015-09-15 21:46:47 +0000 | [diff] [blame] | 1246 | static bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) { | 
|  | 1247 | const Type *BaseType = BaseInit->getBaseClass(); | 
|  | 1248 | const auto *BaseClassDecl = | 
|  | 1249 | cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); | 
|  | 1250 | return BaseClassDecl->isDynamicClass(); | 
|  | 1251 | } | 
|  | 1252 |  | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 1253 | /// EmitCtorPrologue - This routine generates necessary code to initialize | 
|  | 1254 | /// base classes and non-static data members belonging to this constructor. | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 1255 | void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, | 
| Douglas Gregor | 94f9a48 | 2010-05-05 05:51:00 +0000 | [diff] [blame] | 1256 | CXXCtorType CtorType, | 
|  | 1257 | FunctionArgList &Args) { | 
| Alexis Hunt | 61bc173 | 2011-05-01 07:04:31 +0000 | [diff] [blame] | 1258 | if (CD->isDelegatingConstructor()) | 
|  | 1259 | return EmitDelegatingCXXConstructorCall(CD, Args); | 
|  | 1260 |  | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 1261 | const CXXRecordDecl *ClassDecl = CD->getParent(); | 
| Anders Carlsson | 5dc8633 | 2010-02-02 19:58:43 +0000 | [diff] [blame] | 1262 |  | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1263 | CXXConstructorDecl::init_const_iterator B = CD->init_begin(), | 
|  | 1264 | E = CD->init_end(); | 
|  | 1265 |  | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1266 | llvm::BasicBlock *BaseCtorContinueBB = nullptr; | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1267 | if (ClassDecl->getNumVBases() && | 
|  | 1268 | !CGM.getTarget().getCXXABI().hasConstructorVariants()) { | 
|  | 1269 | // The ABIs that don't have constructor variants need to put a branch | 
|  | 1270 | // before the virtual base initialization code. | 
| Reid Kleckner | 7810af0 | 2013-06-19 15:20:38 +0000 | [diff] [blame] | 1271 | BaseCtorContinueBB = | 
|  | 1272 | CGM.getCXXABI().EmitCtorCompleteObjectHandler(*this, ClassDecl); | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1273 | assert(BaseCtorContinueBB); | 
|  | 1274 | } | 
|  | 1275 |  | 
| Piotr Padlewski | 276a78d | 2015-10-02 22:12:40 +0000 | [diff] [blame] | 1276 | llvm::Value *const OldThis = CXXThisValue; | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1277 | // Virtual base initializers first. | 
|  | 1278 | for (; B != E && (*B)->isBaseInitializer() && (*B)->isBaseVirtual(); B++) { | 
| Piotr Padlewski | 276a78d | 2015-10-02 22:12:40 +0000 | [diff] [blame] | 1279 | if (CGM.getCodeGenOpts().StrictVTablePointers && | 
|  | 1280 | CGM.getCodeGenOpts().OptimizationLevel > 0 && | 
|  | 1281 | isInitializerOfDynamicClass(*B)) | 
| Piotr Padlewski | 5dde809 | 2018-05-03 11:03:01 +0000 | [diff] [blame] | 1282 | CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis()); | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1283 | EmitBaseInitializer(*this, ClassDecl, *B, CtorType); | 
|  | 1284 | } | 
|  | 1285 |  | 
|  | 1286 | if (BaseCtorContinueBB) { | 
|  | 1287 | // Complete object handler should continue to the remaining initializers. | 
|  | 1288 | Builder.CreateBr(BaseCtorContinueBB); | 
|  | 1289 | EmitBlock(BaseCtorContinueBB); | 
|  | 1290 | } | 
|  | 1291 |  | 
|  | 1292 | // Then, non-virtual base initializers. | 
|  | 1293 | for (; B != E && (*B)->isBaseInitializer(); B++) { | 
|  | 1294 | assert(!(*B)->isBaseVirtual()); | 
| Piotr Padlewski | 276a78d | 2015-10-02 22:12:40 +0000 | [diff] [blame] | 1295 |  | 
|  | 1296 | if (CGM.getCodeGenOpts().StrictVTablePointers && | 
|  | 1297 | CGM.getCodeGenOpts().OptimizationLevel > 0 && | 
|  | 1298 | isInitializerOfDynamicClass(*B)) | 
| Piotr Padlewski | 5dde809 | 2018-05-03 11:03:01 +0000 | [diff] [blame] | 1299 | CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis()); | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1300 | EmitBaseInitializer(*this, ClassDecl, *B, CtorType); | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 1301 | } | 
|  | 1302 |  | 
| Piotr Padlewski | 276a78d | 2015-10-02 22:12:40 +0000 | [diff] [blame] | 1303 | CXXThisValue = OldThis; | 
| Piotr Padlewski | 338c9d0 | 2015-09-15 21:46:47 +0000 | [diff] [blame] | 1304 |  | 
| Anders Carlsson | d589593 | 2010-03-28 21:07:49 +0000 | [diff] [blame] | 1305 | InitializeVTablePointers(ClassDecl); | 
| Anders Carlsson | 5dc8633 | 2010-02-02 19:58:43 +0000 | [diff] [blame] | 1306 |  | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1307 | // And finally, initialize class members. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1308 | FieldConstructionScope FCS(*this, LoadCXXThisAddress()); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1309 | ConstructorMemcpyizer CM(*this, CD, Args); | 
| Timur Iskhodzhanov | 57cbe5c | 2013-02-27 13:46:31 +0000 | [diff] [blame] | 1310 | for (; B != E; B++) { | 
|  | 1311 | CXXCtorInitializer *Member = (*B); | 
|  | 1312 | assert(!Member->isBaseInitializer()); | 
|  | 1313 | assert(Member->isAnyMemberInitializer() && | 
|  | 1314 | "Delegating initializer on non-delegating constructor"); | 
|  | 1315 | CM.addMemberInitializer(Member); | 
|  | 1316 | } | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1317 | CM.finish(); | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 1318 | } | 
|  | 1319 |  | 
| Anders Carlsson | 49c0bd2 | 2011-05-15 17:36:21 +0000 | [diff] [blame] | 1320 | static bool | 
|  | 1321 | FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field); | 
|  | 1322 |  | 
|  | 1323 | static bool | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1324 | HasTrivialDestructorBody(ASTContext &Context, | 
| Anders Carlsson | 49c0bd2 | 2011-05-15 17:36:21 +0000 | [diff] [blame] | 1325 | const CXXRecordDecl *BaseClassDecl, | 
|  | 1326 | const CXXRecordDecl *MostDerivedClassDecl) | 
|  | 1327 | { | 
|  | 1328 | // If the destructor is trivial we don't have to check anything else. | 
|  | 1329 | if (BaseClassDecl->hasTrivialDestructor()) | 
|  | 1330 | return true; | 
|  | 1331 |  | 
|  | 1332 | if (!BaseClassDecl->getDestructor()->hasTrivialBody()) | 
|  | 1333 | return false; | 
|  | 1334 |  | 
|  | 1335 | // Check fields. | 
| Aaron Ballman | e8a8bae | 2014-03-08 20:12:42 +0000 | [diff] [blame] | 1336 | for (const auto *Field : BaseClassDecl->fields()) | 
| Anders Carlsson | 49c0bd2 | 2011-05-15 17:36:21 +0000 | [diff] [blame] | 1337 | if (!FieldHasTrivialDestructorBody(Context, Field)) | 
|  | 1338 | return false; | 
| Anders Carlsson | 49c0bd2 | 2011-05-15 17:36:21 +0000 | [diff] [blame] | 1339 |  | 
|  | 1340 | // Check non-virtual bases. | 
| Aaron Ballman | 574705e | 2014-03-13 15:41:46 +0000 | [diff] [blame] | 1341 | for (const auto &I : BaseClassDecl->bases()) { | 
|  | 1342 | if (I.isVirtual()) | 
| Anders Carlsson | 49c0bd2 | 2011-05-15 17:36:21 +0000 | [diff] [blame] | 1343 | continue; | 
|  | 1344 |  | 
|  | 1345 | const CXXRecordDecl *NonVirtualBase = | 
| Aaron Ballman | 574705e | 2014-03-13 15:41:46 +0000 | [diff] [blame] | 1346 | cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); | 
| Anders Carlsson | 49c0bd2 | 2011-05-15 17:36:21 +0000 | [diff] [blame] | 1347 | if (!HasTrivialDestructorBody(Context, NonVirtualBase, | 
|  | 1348 | MostDerivedClassDecl)) | 
|  | 1349 | return false; | 
|  | 1350 | } | 
|  | 1351 |  | 
|  | 1352 | if (BaseClassDecl == MostDerivedClassDecl) { | 
|  | 1353 | // Check virtual bases. | 
| Aaron Ballman | 445a939 | 2014-03-13 16:15:17 +0000 | [diff] [blame] | 1354 | for (const auto &I : BaseClassDecl->vbases()) { | 
| Anders Carlsson | 49c0bd2 | 2011-05-15 17:36:21 +0000 | [diff] [blame] | 1355 | const CXXRecordDecl *VirtualBase = | 
| Aaron Ballman | 445a939 | 2014-03-13 16:15:17 +0000 | [diff] [blame] | 1356 | cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); | 
| Anders Carlsson | 49c0bd2 | 2011-05-15 17:36:21 +0000 | [diff] [blame] | 1357 | if (!HasTrivialDestructorBody(Context, VirtualBase, | 
|  | 1358 | MostDerivedClassDecl)) | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1359 | return false; | 
| Anders Carlsson | 49c0bd2 | 2011-05-15 17:36:21 +0000 | [diff] [blame] | 1360 | } | 
|  | 1361 | } | 
|  | 1362 |  | 
|  | 1363 | return true; | 
|  | 1364 | } | 
|  | 1365 |  | 
|  | 1366 | static bool | 
|  | 1367 | FieldHasTrivialDestructorBody(ASTContext &Context, | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1368 | const FieldDecl *Field) | 
| Anders Carlsson | 49c0bd2 | 2011-05-15 17:36:21 +0000 | [diff] [blame] | 1369 | { | 
|  | 1370 | QualType FieldBaseElementType = Context.getBaseElementType(Field->getType()); | 
|  | 1371 |  | 
|  | 1372 | const RecordType *RT = FieldBaseElementType->getAs<RecordType>(); | 
|  | 1373 | if (!RT) | 
|  | 1374 | return true; | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1375 |  | 
| Anders Carlsson | 49c0bd2 | 2011-05-15 17:36:21 +0000 | [diff] [blame] | 1376 | CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); | 
| Davide Italiano | 982bbf4 | 2015-06-26 00:18:35 +0000 | [diff] [blame] | 1377 |  | 
|  | 1378 | // The destructor for an implicit anonymous union member is never invoked. | 
|  | 1379 | if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion()) | 
|  | 1380 | return false; | 
|  | 1381 |  | 
| Anders Carlsson | 49c0bd2 | 2011-05-15 17:36:21 +0000 | [diff] [blame] | 1382 | return HasTrivialDestructorBody(Context, FieldClassDecl, FieldClassDecl); | 
|  | 1383 | } | 
|  | 1384 |  | 
| Anders Carlsson | 9bd7d16 | 2011-05-14 23:26:09 +0000 | [diff] [blame] | 1385 | /// CanSkipVTablePointerInitialization - Check whether we need to initialize | 
|  | 1386 | /// any vtable pointers before calling this destructor. | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1387 | static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF, | 
| Anders Carlsson | d6f1518 | 2011-05-16 04:08:36 +0000 | [diff] [blame] | 1388 | const CXXDestructorDecl *Dtor) { | 
| Piotr Padlewski | 338c9d0 | 2015-09-15 21:46:47 +0000 | [diff] [blame] | 1389 | const CXXRecordDecl *ClassDecl = Dtor->getParent(); | 
|  | 1390 | if (!ClassDecl->isDynamicClass()) | 
|  | 1391 | return true; | 
|  | 1392 |  | 
| Anders Carlsson | 9bd7d16 | 2011-05-14 23:26:09 +0000 | [diff] [blame] | 1393 | if (!Dtor->hasTrivialBody()) | 
|  | 1394 | return false; | 
|  | 1395 |  | 
|  | 1396 | // Check the fields. | 
| Aaron Ballman | e8a8bae | 2014-03-08 20:12:42 +0000 | [diff] [blame] | 1397 | for (const auto *Field : ClassDecl->fields()) | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1398 | if (!FieldHasTrivialDestructorBody(CGF.getContext(), Field)) | 
| Anders Carlsson | 49c0bd2 | 2011-05-15 17:36:21 +0000 | [diff] [blame] | 1399 | return false; | 
| Anders Carlsson | 9bd7d16 | 2011-05-14 23:26:09 +0000 | [diff] [blame] | 1400 |  | 
|  | 1401 | return true; | 
|  | 1402 | } | 
|  | 1403 |  | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 1404 | /// EmitDestructorBody - Emits the body of the current destructor. | 
|  | 1405 | void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { | 
|  | 1406 | const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl()); | 
|  | 1407 | CXXDtorType DtorType = CurGD.getDtorType(); | 
|  | 1408 |  | 
| Richard Smith | df054d3 | 2017-02-25 23:53:05 +0000 | [diff] [blame] | 1409 | // For an abstract class, non-base destructors are never used (and can't | 
|  | 1410 | // be emitted in general, because vbase dtors may not have been validated | 
|  | 1411 | // by Sema), but the Itanium ABI doesn't make them optional and Clang may | 
|  | 1412 | // in fact emit references to them from other compilations, so emit them | 
|  | 1413 | // as functions containing a trap instruction. | 
|  | 1414 | if (DtorType != Dtor_Base && Dtor->getParent()->isAbstract()) { | 
|  | 1415 | llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap); | 
|  | 1416 | TrapCall->setDoesNotReturn(); | 
|  | 1417 | TrapCall->setDoesNotThrow(); | 
|  | 1418 | Builder.CreateUnreachable(); | 
|  | 1419 | Builder.ClearInsertionPoint(); | 
|  | 1420 | return; | 
|  | 1421 | } | 
|  | 1422 |  | 
| Justin Bogner | fb29822 | 2015-05-20 16:16:23 +0000 | [diff] [blame] | 1423 | Stmt *Body = Dtor->getBody(); | 
|  | 1424 | if (Body) | 
|  | 1425 | incrementProfileCounter(Body); | 
|  | 1426 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1427 | // The call to operator delete in a deleting destructor happens | 
|  | 1428 | // outside of the function-try-block, which means it's always | 
|  | 1429 | // possible to delegate the destructor body to the complete | 
|  | 1430 | // destructor.  Do so. | 
|  | 1431 | if (DtorType == Dtor_Deleting) { | 
| Richard Smith | 5b34958 | 2017-10-13 01:55:36 +0000 | [diff] [blame] | 1432 | RunCleanupsScope DtorEpilogue(*this); | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1433 | EnterDtorCleanups(Dtor, Dtor_Deleting); | 
| Richard Smith | 5b34958 | 2017-10-13 01:55:36 +0000 | [diff] [blame] | 1434 | if (HaveInsertPoint()) | 
|  | 1435 | EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, | 
|  | 1436 | /*Delegating=*/false, LoadCXXThisAddress()); | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1437 | return; | 
|  | 1438 | } | 
|  | 1439 |  | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 1440 | // If the body is a function-try-block, enter the try before | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1441 | // anything else. | 
|  | 1442 | bool isTryBody = (Body && isa<CXXTryStmt>(Body)); | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 1443 | if (isTryBody) | 
| John McCall | b609d3f | 2010-07-07 06:56:46 +0000 | [diff] [blame] | 1444 | EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true); | 
| Kostya Serebryany | 293dc9b | 2014-10-16 20:54:52 +0000 | [diff] [blame] | 1445 | EmitAsanPrologueOrEpilogue(false); | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 1446 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1447 | // Enter the epilogue cleanups. | 
|  | 1448 | RunCleanupsScope DtorEpilogue(*this); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1449 |  | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 1450 | // If this is the complete variant, just invoke the base variant; | 
|  | 1451 | // the epilogue will destruct the virtual bases.  But we can't do | 
|  | 1452 | // this optimization if the body is a function-try-block, because | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1453 | // we'd introduce *two* handler blocks.  In the Microsoft ABI, we | 
| Reid Kleckner | e7de47e | 2013-07-22 13:51:44 +0000 | [diff] [blame] | 1454 | // always delegate because we might not have a definition in this TU. | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1455 | switch (DtorType) { | 
| Saleem Abdulrasool | 8de4e87 | 2017-02-02 05:45:43 +0000 | [diff] [blame] | 1456 | case Dtor_Comdat: llvm_unreachable("not expecting a COMDAT"); | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1457 | case Dtor_Deleting: llvm_unreachable("already handled deleting case"); | 
|  | 1458 |  | 
|  | 1459 | case Dtor_Complete: | 
| Reid Kleckner | e7de47e | 2013-07-22 13:51:44 +0000 | [diff] [blame] | 1460 | assert((Body || getTarget().getCXXABI().isMicrosoft()) && | 
|  | 1461 | "can't emit a dtor without a body for non-Microsoft ABIs"); | 
|  | 1462 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1463 | // Enter the cleanup scopes for virtual bases. | 
|  | 1464 | EnterDtorCleanups(Dtor, Dtor_Complete); | 
|  | 1465 |  | 
| Reid Kleckner | e7de47e | 2013-07-22 13:51:44 +0000 | [diff] [blame] | 1466 | if (!isTryBody) { | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1467 | EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1468 | /*Delegating=*/false, LoadCXXThisAddress()); | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1469 | break; | 
|  | 1470 | } | 
| Saleem Abdulrasool | 8de4e87 | 2017-02-02 05:45:43 +0000 | [diff] [blame] | 1471 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1472 | // Fallthrough: act like we're in the base variant. | 
| Saleem Abdulrasool | 8de4e87 | 2017-02-02 05:45:43 +0000 | [diff] [blame] | 1473 | LLVM_FALLTHROUGH; | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1474 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1475 | case Dtor_Base: | 
| Reid Kleckner | e7de47e | 2013-07-22 13:51:44 +0000 | [diff] [blame] | 1476 | assert(Body); | 
|  | 1477 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1478 | // Enter the cleanup scopes for fields and non-virtual bases. | 
|  | 1479 | EnterDtorCleanups(Dtor, Dtor_Base); | 
|  | 1480 |  | 
|  | 1481 | // Initialize the vtable pointers before entering the body. | 
| Piotr Padlewski | 338c9d0 | 2015-09-15 21:46:47 +0000 | [diff] [blame] | 1482 | if (!CanSkipVTablePointerInitialization(*this, Dtor)) { | 
| Piotr Padlewski | 5dde809 | 2018-05-03 11:03:01 +0000 | [diff] [blame] | 1483 | // Insert the llvm.launder.invariant.group intrinsic before initializing | 
| Piotr Padlewski | 338c9d0 | 2015-09-15 21:46:47 +0000 | [diff] [blame] | 1484 | // the vptrs to cancel any previous assumptions we might have made. | 
|  | 1485 | if (CGM.getCodeGenOpts().StrictVTablePointers && | 
|  | 1486 | CGM.getCodeGenOpts().OptimizationLevel > 0) | 
| Piotr Padlewski | 5dde809 | 2018-05-03 11:03:01 +0000 | [diff] [blame] | 1487 | CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis()); | 
| Piotr Padlewski | 338c9d0 | 2015-09-15 21:46:47 +0000 | [diff] [blame] | 1488 | InitializeVTablePointers(Dtor->getParent()); | 
|  | 1489 | } | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1490 |  | 
|  | 1491 | if (isTryBody) | 
|  | 1492 | EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock()); | 
|  | 1493 | else if (Body) | 
|  | 1494 | EmitStmt(Body); | 
|  | 1495 | else { | 
|  | 1496 | assert(Dtor->isImplicit() && "bodyless dtor not implicit"); | 
|  | 1497 | // nothing to do besides what's in the epilogue | 
|  | 1498 | } | 
| Fariborz Jahanian | 0c12ed1 | 2011-02-02 23:12:46 +0000 | [diff] [blame] | 1499 | // -fapple-kext must inline any call to this dtor into | 
|  | 1500 | // the caller's body. | 
| Richard Smith | 9c6890a | 2012-11-01 22:30:59 +0000 | [diff] [blame] | 1501 | if (getLangOpts().AppleKext) | 
| Evgeniy Stepanov | 6b2a61d | 2015-09-14 21:35:16 +0000 | [diff] [blame] | 1502 | CurFn->addFnAttr(llvm::Attribute::AlwaysInline); | 
| Naomi Musgrave | e50cb9b | 2015-08-13 18:35:11 +0000 | [diff] [blame] | 1503 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1504 | break; | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 1505 | } | 
|  | 1506 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1507 | // Jump out through the epilogue cleanups. | 
|  | 1508 | DtorEpilogue.ForceCleanup(); | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 1509 |  | 
|  | 1510 | // Exit the try if applicable. | 
|  | 1511 | if (isTryBody) | 
| John McCall | b609d3f | 2010-07-07 06:56:46 +0000 | [diff] [blame] | 1512 | ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true); | 
| John McCall | b81884d | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 1513 | } | 
|  | 1514 |  | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1515 | void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args) { | 
|  | 1516 | const CXXMethodDecl *AssignOp = cast<CXXMethodDecl>(CurGD.getDecl()); | 
|  | 1517 | const Stmt *RootS = AssignOp->getBody(); | 
|  | 1518 | assert(isa<CompoundStmt>(RootS) && | 
|  | 1519 | "Body of an implicit assignment operator should be compound stmt."); | 
|  | 1520 | const CompoundStmt *RootCS = cast<CompoundStmt>(RootS); | 
|  | 1521 |  | 
|  | 1522 | LexicalScope Scope(*this, RootCS->getSourceRange()); | 
|  | 1523 |  | 
| Xinliang David Li | a951e8e | 2016-02-09 20:02:59 +0000 | [diff] [blame] | 1524 | incrementProfileCounter(RootCS); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1525 | AssignmentMemcpyizer AM(*this, AssignOp, Args); | 
| Aaron Ballman | c7e4e21 | 2014-03-17 14:19:37 +0000 | [diff] [blame] | 1526 | for (auto *I : RootCS->body()) | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1527 | AM.emitAssignment(I); | 
| Lang Hames | bf12274 | 2013-02-17 07:22:09 +0000 | [diff] [blame] | 1528 | AM.finish(); | 
|  | 1529 | } | 
|  | 1530 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1531 | namespace { | 
| Richard Smith | 5b34958 | 2017-10-13 01:55:36 +0000 | [diff] [blame] | 1532 | llvm::Value *LoadThisForDtorDelete(CodeGenFunction &CGF, | 
|  | 1533 | const CXXDestructorDecl *DD) { | 
|  | 1534 | if (Expr *ThisArg = DD->getOperatorDeleteThisArg()) | 
| Haojian Wu | 5b5c81f | 2017-10-13 15:37:53 +0000 | [diff] [blame] | 1535 | return CGF.EmitScalarExpr(ThisArg); | 
| Richard Smith | 5b34958 | 2017-10-13 01:55:36 +0000 | [diff] [blame] | 1536 | return CGF.LoadCXXThis(); | 
|  | 1537 | } | 
|  | 1538 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1539 | /// Call the operator delete associated with the current destructor. | 
| David Blaikie | 7e70d68 | 2015-08-18 22:40:54 +0000 | [diff] [blame] | 1540 | struct CallDtorDelete final : EHScopeStack::Cleanup { | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1541 | CallDtorDelete() {} | 
|  | 1542 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 1543 | void Emit(CodeGenFunction &CGF, Flags flags) override { | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1544 | const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl); | 
|  | 1545 | const CXXRecordDecl *ClassDecl = Dtor->getParent(); | 
| Richard Smith | 5b34958 | 2017-10-13 01:55:36 +0000 | [diff] [blame] | 1546 | CGF.EmitDeleteCall(Dtor->getOperatorDelete(), | 
|  | 1547 | LoadThisForDtorDelete(CGF, Dtor), | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1548 | CGF.getContext().getTagDeclType(ClassDecl)); | 
|  | 1549 | } | 
|  | 1550 | }; | 
|  | 1551 |  | 
| Richard Smith | 5b34958 | 2017-10-13 01:55:36 +0000 | [diff] [blame] | 1552 | void EmitConditionalDtorDeleteCall(CodeGenFunction &CGF, | 
|  | 1553 | llvm::Value *ShouldDeleteCondition, | 
|  | 1554 | bool ReturnAfterDelete) { | 
|  | 1555 | llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete"); | 
|  | 1556 | llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue"); | 
|  | 1557 | llvm::Value *ShouldCallDelete | 
|  | 1558 | = CGF.Builder.CreateIsNull(ShouldDeleteCondition); | 
|  | 1559 | CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB); | 
|  | 1560 |  | 
|  | 1561 | CGF.EmitBlock(callDeleteBB); | 
|  | 1562 | const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl); | 
|  | 1563 | const CXXRecordDecl *ClassDecl = Dtor->getParent(); | 
|  | 1564 | CGF.EmitDeleteCall(Dtor->getOperatorDelete(), | 
|  | 1565 | LoadThisForDtorDelete(CGF, Dtor), | 
|  | 1566 | CGF.getContext().getTagDeclType(ClassDecl)); | 
|  | 1567 | assert(Dtor->getOperatorDelete()->isDestroyingOperatorDelete() == | 
|  | 1568 | ReturnAfterDelete && | 
|  | 1569 | "unexpected value for ReturnAfterDelete"); | 
|  | 1570 | if (ReturnAfterDelete) | 
|  | 1571 | CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); | 
|  | 1572 | else | 
|  | 1573 | CGF.Builder.CreateBr(continueBB); | 
|  | 1574 |  | 
|  | 1575 | CGF.EmitBlock(continueBB); | 
|  | 1576 | } | 
|  | 1577 |  | 
| David Blaikie | 7e70d68 | 2015-08-18 22:40:54 +0000 | [diff] [blame] | 1578 | struct CallDtorDeleteConditional final : EHScopeStack::Cleanup { | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1579 | llvm::Value *ShouldDeleteCondition; | 
| Eugene Zelenko | 0a4f3f4 | 2016-02-10 19:11:58 +0000 | [diff] [blame] | 1580 |  | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1581 | public: | 
|  | 1582 | CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition) | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1583 | : ShouldDeleteCondition(ShouldDeleteCondition) { | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1584 | assert(ShouldDeleteCondition != nullptr); | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1585 | } | 
|  | 1586 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 1587 | void Emit(CodeGenFunction &CGF, Flags flags) override { | 
| Richard Smith | 5b34958 | 2017-10-13 01:55:36 +0000 | [diff] [blame] | 1588 | EmitConditionalDtorDeleteCall(CGF, ShouldDeleteCondition, | 
|  | 1589 | /*ReturnAfterDelete*/false); | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1590 | } | 
|  | 1591 | }; | 
|  | 1592 |  | 
| David Blaikie | 7e70d68 | 2015-08-18 22:40:54 +0000 | [diff] [blame] | 1593 | class DestroyField  final : public EHScopeStack::Cleanup { | 
| John McCall | 4bd0fb1 | 2011-07-12 16:41:08 +0000 | [diff] [blame] | 1594 | const FieldDecl *field; | 
| Peter Collingbourne | 1425b45 | 2012-01-26 03:33:36 +0000 | [diff] [blame] | 1595 | CodeGenFunction::Destroyer *destroyer; | 
| John McCall | 4bd0fb1 | 2011-07-12 16:41:08 +0000 | [diff] [blame] | 1596 | bool useEHCleanupForArray; | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1597 |  | 
| John McCall | 4bd0fb1 | 2011-07-12 16:41:08 +0000 | [diff] [blame] | 1598 | public: | 
|  | 1599 | DestroyField(const FieldDecl *field, CodeGenFunction::Destroyer *destroyer, | 
|  | 1600 | bool useEHCleanupForArray) | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1601 | : field(field), destroyer(destroyer), | 
|  | 1602 | useEHCleanupForArray(useEHCleanupForArray) {} | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1603 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 1604 | void Emit(CodeGenFunction &CGF, Flags flags) override { | 
| John McCall | 4bd0fb1 | 2011-07-12 16:41:08 +0000 | [diff] [blame] | 1605 | // Find the address of the field. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1606 | Address thisValue = CGF.LoadCXXThisAddress(); | 
| Eli Friedman | 7f1ff60 | 2012-04-16 03:54:45 +0000 | [diff] [blame] | 1607 | QualType RecordTy = CGF.getContext().getTagDeclType(field->getParent()); | 
|  | 1608 | LValue ThisLV = CGF.MakeAddrLValue(thisValue, RecordTy); | 
|  | 1609 | LValue LV = CGF.EmitLValueForField(ThisLV, field); | 
| John McCall | 4bd0fb1 | 2011-07-12 16:41:08 +0000 | [diff] [blame] | 1610 | assert(LV.isSimple()); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1611 |  | 
| John McCall | 4bd0fb1 | 2011-07-12 16:41:08 +0000 | [diff] [blame] | 1612 | CGF.emitDestroy(LV.getAddress(), field->getType(), destroyer, | 
| John McCall | 30317fd | 2011-07-12 20:27:29 +0000 | [diff] [blame] | 1613 | flags.isForNormalCleanup() && useEHCleanupForArray); | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1614 | } | 
|  | 1615 | }; | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1616 |  | 
| Naomi Musgrave | 703835c | 2015-09-16 00:38:22 +0000 | [diff] [blame] | 1617 | static void EmitSanitizerDtorCallback(CodeGenFunction &CGF, llvm::Value *Ptr, | 
|  | 1618 | CharUnits::QuantityType PoisonSize) { | 
| Matt Morehouse | 4881a23 | 2017-09-20 22:53:08 +0000 | [diff] [blame] | 1619 | CodeGenFunction::SanitizerScope SanScope(&CGF); | 
| Naomi Musgrave | 703835c | 2015-09-16 00:38:22 +0000 | [diff] [blame] | 1620 | // Pass in void pointer and size of region as arguments to runtime | 
|  | 1621 | // function | 
|  | 1622 | llvm::Value *Args[] = {CGF.Builder.CreateBitCast(Ptr, CGF.VoidPtrTy), | 
|  | 1623 | llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; | 
|  | 1624 |  | 
|  | 1625 | llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; | 
|  | 1626 |  | 
|  | 1627 | llvm::FunctionType *FnType = | 
|  | 1628 | llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false); | 
|  | 1629 | llvm::Value *Fn = | 
|  | 1630 | CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); | 
|  | 1631 | CGF.EmitNounwindRuntimeCall(Fn, Args); | 
|  | 1632 | } | 
|  | 1633 |  | 
|  | 1634 | class SanitizeDtorMembers final : public EHScopeStack::Cleanup { | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1635 | const CXXDestructorDecl *Dtor; | 
|  | 1636 |  | 
|  | 1637 | public: | 
| Naomi Musgrave | 703835c | 2015-09-16 00:38:22 +0000 | [diff] [blame] | 1638 | SanitizeDtorMembers(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1639 |  | 
|  | 1640 | // Generate function call for handling object poisoning. | 
|  | 1641 | // Disables tail call elimination, to prevent the current stack frame | 
|  | 1642 | // from disappearing from the stack trace. | 
|  | 1643 | void Emit(CodeGenFunction &CGF, Flags flags) override { | 
|  | 1644 | const ASTRecordLayout &Layout = | 
|  | 1645 | CGF.getContext().getASTRecordLayout(Dtor->getParent()); | 
|  | 1646 |  | 
|  | 1647 | // Nothing to poison. | 
|  | 1648 | if (Layout.getFieldCount() == 0) | 
|  | 1649 | return; | 
|  | 1650 |  | 
|  | 1651 | // Prevent the current stack frame from disappearing from the stack trace. | 
|  | 1652 | CGF.CurFn->addFnAttr("disable-tail-calls", "true"); | 
|  | 1653 |  | 
|  | 1654 | // Construct pointer to region to begin poisoning, and calculate poison | 
|  | 1655 | // size, so that only members declared in this class are poisoned. | 
|  | 1656 | ASTContext &Context = CGF.getContext(); | 
|  | 1657 | unsigned fieldIndex = 0; | 
|  | 1658 | int startIndex = -1; | 
|  | 1659 | // RecordDecl::field_iterator Field; | 
|  | 1660 | for (const FieldDecl *Field : Dtor->getParent()->fields()) { | 
|  | 1661 | // Poison field if it is trivial | 
|  | 1662 | if (FieldHasTrivialDestructorBody(Context, Field)) { | 
|  | 1663 | // Start sanitizing at this field | 
|  | 1664 | if (startIndex < 0) | 
|  | 1665 | startIndex = fieldIndex; | 
|  | 1666 |  | 
|  | 1667 | // Currently on the last field, and it must be poisoned with the | 
|  | 1668 | // current block. | 
|  | 1669 | if (fieldIndex == Layout.getFieldCount() - 1) { | 
| Naomi Musgrave | 703835c | 2015-09-16 00:38:22 +0000 | [diff] [blame] | 1670 | PoisonMembers(CGF, startIndex, Layout.getFieldCount()); | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1671 | } | 
|  | 1672 | } else if (startIndex >= 0) { | 
|  | 1673 | // No longer within a block of memory to poison, so poison the block | 
| Naomi Musgrave | 703835c | 2015-09-16 00:38:22 +0000 | [diff] [blame] | 1674 | PoisonMembers(CGF, startIndex, fieldIndex); | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1675 | // Re-set the start index | 
|  | 1676 | startIndex = -1; | 
|  | 1677 | } | 
|  | 1678 | fieldIndex += 1; | 
|  | 1679 | } | 
|  | 1680 | } | 
|  | 1681 |  | 
|  | 1682 | private: | 
| NAKAMURA Takumi | f6cef72f | 2015-09-04 05:19:31 +0000 | [diff] [blame] | 1683 | /// \param layoutStartOffset index of the ASTRecordLayout field to | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1684 | ///     start poisoning (inclusive) | 
| NAKAMURA Takumi | f6cef72f | 2015-09-04 05:19:31 +0000 | [diff] [blame] | 1685 | /// \param layoutEndOffset index of the ASTRecordLayout field to | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1686 | ///     end poisoning (exclusive) | 
| Naomi Musgrave | 703835c | 2015-09-16 00:38:22 +0000 | [diff] [blame] | 1687 | void PoisonMembers(CodeGenFunction &CGF, unsigned layoutStartOffset, | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1688 | unsigned layoutEndOffset) { | 
|  | 1689 | ASTContext &Context = CGF.getContext(); | 
|  | 1690 | const ASTRecordLayout &Layout = | 
|  | 1691 | Context.getASTRecordLayout(Dtor->getParent()); | 
|  | 1692 |  | 
|  | 1693 | llvm::ConstantInt *OffsetSizePtr = llvm::ConstantInt::get( | 
|  | 1694 | CGF.SizeTy, | 
|  | 1695 | Context.toCharUnitsFromBits(Layout.getFieldOffset(layoutStartOffset)) | 
|  | 1696 | .getQuantity()); | 
|  | 1697 |  | 
|  | 1698 | llvm::Value *OffsetPtr = CGF.Builder.CreateGEP( | 
|  | 1699 | CGF.Builder.CreateBitCast(CGF.LoadCXXThis(), CGF.Int8PtrTy), | 
|  | 1700 | OffsetSizePtr); | 
|  | 1701 |  | 
|  | 1702 | CharUnits::QuantityType PoisonSize; | 
|  | 1703 | if (layoutEndOffset >= Layout.getFieldCount()) { | 
|  | 1704 | PoisonSize = Layout.getNonVirtualSize().getQuantity() - | 
|  | 1705 | Context.toCharUnitsFromBits( | 
|  | 1706 | Layout.getFieldOffset(layoutStartOffset)) | 
|  | 1707 | .getQuantity(); | 
|  | 1708 | } else { | 
|  | 1709 | PoisonSize = Context.toCharUnitsFromBits( | 
|  | 1710 | Layout.getFieldOffset(layoutEndOffset) - | 
|  | 1711 | Layout.getFieldOffset(layoutStartOffset)) | 
|  | 1712 | .getQuantity(); | 
|  | 1713 | } | 
|  | 1714 |  | 
|  | 1715 | if (PoisonSize == 0) | 
|  | 1716 | return; | 
|  | 1717 |  | 
| Naomi Musgrave | 703835c | 2015-09-16 00:38:22 +0000 | [diff] [blame] | 1718 | EmitSanitizerDtorCallback(CGF, OffsetPtr, PoisonSize); | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1719 | } | 
|  | 1720 | }; | 
| Naomi Musgrave | 703835c | 2015-09-16 00:38:22 +0000 | [diff] [blame] | 1721 |  | 
|  | 1722 | class SanitizeDtorVTable final : public EHScopeStack::Cleanup { | 
|  | 1723 | const CXXDestructorDecl *Dtor; | 
|  | 1724 |  | 
|  | 1725 | public: | 
|  | 1726 | SanitizeDtorVTable(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} | 
|  | 1727 |  | 
|  | 1728 | // Generate function call for handling vtable pointer poisoning. | 
|  | 1729 | void Emit(CodeGenFunction &CGF, Flags flags) override { | 
|  | 1730 | assert(Dtor->getParent()->isDynamicClass()); | 
| NAKAMURA Takumi | ee82b49 | 2015-09-16 06:26:56 +0000 | [diff] [blame] | 1731 | (void)Dtor; | 
| Naomi Musgrave | 703835c | 2015-09-16 00:38:22 +0000 | [diff] [blame] | 1732 | ASTContext &Context = CGF.getContext(); | 
|  | 1733 | // Poison vtable and vtable ptr if they exist for this class. | 
|  | 1734 | llvm::Value *VTablePtr = CGF.LoadCXXThis(); | 
|  | 1735 |  | 
|  | 1736 | CharUnits::QuantityType PoisonSize = | 
|  | 1737 | Context.toCharUnitsFromBits(CGF.PointerWidthInBits).getQuantity(); | 
|  | 1738 | // Pass in void pointer and size of region as arguments to runtime | 
|  | 1739 | // function | 
|  | 1740 | EmitSanitizerDtorCallback(CGF, VTablePtr, PoisonSize); | 
|  | 1741 | } | 
|  | 1742 | }; | 
| Hans Wennborg | dcfba33 | 2015-10-06 23:40:43 +0000 | [diff] [blame] | 1743 | } // end anonymous namespace | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1744 |  | 
| Adrian Prantl | 9fc8faf | 2018-05-09 01:00:01 +0000 | [diff] [blame] | 1745 | /// Emit all code that comes at the end of class's | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 1746 | /// destructor. This is to call destructors on members and base classes | 
|  | 1747 | /// in reverse order of their construction. | 
| Richard Smith | 5b34958 | 2017-10-13 01:55:36 +0000 | [diff] [blame] | 1748 | /// | 
|  | 1749 | /// For a deleting destructor, this also handles the case where a destroying | 
|  | 1750 | /// operator delete completely overrides the definition. | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1751 | void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD, | 
|  | 1752 | CXXDtorType DtorType) { | 
| Hans Wennborg | 853ae94 | 2014-05-30 16:59:42 +0000 | [diff] [blame] | 1753 | assert((!DD->isTrivial() || DD->hasAttr<DLLExportAttr>()) && | 
|  | 1754 | "Should not emit dtor epilogue for non-exported trivial dtor!"); | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 1755 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1756 | // The deleting-destructor phase just needs to call the appropriate | 
|  | 1757 | // operator delete that Sema picked up. | 
| John McCall | 5c60a6f | 2010-02-18 19:59:28 +0000 | [diff] [blame] | 1758 | if (DtorType == Dtor_Deleting) { | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1759 | assert(DD->getOperatorDelete() && | 
| Hans Wennborg | deff703 | 2013-12-18 01:39:59 +0000 | [diff] [blame] | 1760 | "operator delete missing - EnterDtorCleanups"); | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1761 | if (CXXStructorImplicitParamValue) { | 
|  | 1762 | // If there is an implicit param to the deleting dtor, it's a boolean | 
| Richard Smith | 5b34958 | 2017-10-13 01:55:36 +0000 | [diff] [blame] | 1763 | // telling whether this is a deleting destructor. | 
|  | 1764 | if (DD->getOperatorDelete()->isDestroyingOperatorDelete()) | 
|  | 1765 | EmitConditionalDtorDeleteCall(*this, CXXStructorImplicitParamValue, | 
|  | 1766 | /*ReturnAfterDelete*/true); | 
|  | 1767 | else | 
|  | 1768 | EHStack.pushCleanup<CallDtorDeleteConditional>( | 
|  | 1769 | NormalAndEHCleanup, CXXStructorImplicitParamValue); | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1770 | } else { | 
| Richard Smith | 5b34958 | 2017-10-13 01:55:36 +0000 | [diff] [blame] | 1771 | if (DD->getOperatorDelete()->isDestroyingOperatorDelete()) { | 
|  | 1772 | const CXXRecordDecl *ClassDecl = DD->getParent(); | 
|  | 1773 | EmitDeleteCall(DD->getOperatorDelete(), | 
|  | 1774 | LoadThisForDtorDelete(*this, DD), | 
|  | 1775 | getContext().getTagDeclType(ClassDecl)); | 
|  | 1776 | EmitBranchThroughCleanup(ReturnBlock); | 
|  | 1777 | } else { | 
|  | 1778 | EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup); | 
|  | 1779 | } | 
| Timur Iskhodzhanov | ee6bc53 | 2013-02-13 08:37:51 +0000 | [diff] [blame] | 1780 | } | 
| John McCall | 5c60a6f | 2010-02-18 19:59:28 +0000 | [diff] [blame] | 1781 | return; | 
|  | 1782 | } | 
|  | 1783 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1784 | const CXXRecordDecl *ClassDecl = DD->getParent(); | 
|  | 1785 |  | 
| Richard Smith | 2010404 | 2011-09-18 12:11:43 +0000 | [diff] [blame] | 1786 | // Unions have no bases and do not call field destructors. | 
|  | 1787 | if (ClassDecl->isUnion()) | 
|  | 1788 | return; | 
|  | 1789 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1790 | // The complete-destructor phase just destructs all the virtual bases. | 
| John McCall | 5c60a6f | 2010-02-18 19:59:28 +0000 | [diff] [blame] | 1791 | if (DtorType == Dtor_Complete) { | 
| Naomi Musgrave | 703835c | 2015-09-16 00:38:22 +0000 | [diff] [blame] | 1792 | // Poison the vtable pointer such that access after the base | 
|  | 1793 | // and member destructors are invoked is invalid. | 
|  | 1794 | if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor && | 
|  | 1795 | SanOpts.has(SanitizerKind::Memory) && ClassDecl->getNumVBases() && | 
|  | 1796 | ClassDecl->isPolymorphic()) | 
|  | 1797 | EHStack.pushCleanup<SanitizeDtorVTable>(NormalAndEHCleanup, DD); | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1798 |  | 
|  | 1799 | // We push them in the forward order so that they'll be popped in | 
|  | 1800 | // the reverse order. | 
| Aaron Ballman | 445a939 | 2014-03-13 16:15:17 +0000 | [diff] [blame] | 1801 | for (const auto &Base : ClassDecl->vbases()) { | 
| John McCall | 5c60a6f | 2010-02-18 19:59:28 +0000 | [diff] [blame] | 1802 | CXXRecordDecl *BaseClassDecl | 
|  | 1803 | = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1804 |  | 
| John McCall | 5c60a6f | 2010-02-18 19:59:28 +0000 | [diff] [blame] | 1805 | // Ignore trivial destructors. | 
|  | 1806 | if (BaseClassDecl->hasTrivialDestructor()) | 
|  | 1807 | continue; | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1808 |  | 
| John McCall | cda666c | 2010-07-21 07:22:38 +0000 | [diff] [blame] | 1809 | EHStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, | 
|  | 1810 | BaseClassDecl, | 
|  | 1811 | /*BaseIsVirtual*/ true); | 
| John McCall | 5c60a6f | 2010-02-18 19:59:28 +0000 | [diff] [blame] | 1812 | } | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1813 |  | 
| John McCall | 5c60a6f | 2010-02-18 19:59:28 +0000 | [diff] [blame] | 1814 | return; | 
|  | 1815 | } | 
|  | 1816 |  | 
|  | 1817 | assert(DtorType == Dtor_Base); | 
| Naomi Musgrave | 703835c | 2015-09-16 00:38:22 +0000 | [diff] [blame] | 1818 | // Poison the vtable pointer if it has no virtual bases, but inherits | 
|  | 1819 | // virtual functions. | 
|  | 1820 | if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor && | 
|  | 1821 | SanOpts.has(SanitizerKind::Memory) && !ClassDecl->getNumVBases() && | 
|  | 1822 | ClassDecl->isPolymorphic()) | 
|  | 1823 | EHStack.pushCleanup<SanitizeDtorVTable>(NormalAndEHCleanup, DD); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1824 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1825 | // Destroy non-virtual bases. | 
| Aaron Ballman | 574705e | 2014-03-13 15:41:46 +0000 | [diff] [blame] | 1826 | for (const auto &Base : ClassDecl->bases()) { | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1827 | // Ignore virtual bases. | 
|  | 1828 | if (Base.isVirtual()) | 
|  | 1829 | continue; | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1830 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1831 | CXXRecordDecl *BaseClassDecl = Base.getType()->getAsCXXRecordDecl(); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1832 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1833 | // Ignore trivial destructors. | 
|  | 1834 | if (BaseClassDecl->hasTrivialDestructor()) | 
|  | 1835 | continue; | 
| John McCall | 5c60a6f | 2010-02-18 19:59:28 +0000 | [diff] [blame] | 1836 |  | 
| John McCall | cda666c | 2010-07-21 07:22:38 +0000 | [diff] [blame] | 1837 | EHStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, | 
|  | 1838 | BaseClassDecl, | 
|  | 1839 | /*BaseIsVirtual*/ false); | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1840 | } | 
|  | 1841 |  | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1842 | // Poison fields such that access after their destructors are | 
|  | 1843 | // invoked, and before the base class destructor runs, is invalid. | 
|  | 1844 | if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor && | 
|  | 1845 | SanOpts.has(SanitizerKind::Memory)) | 
| Naomi Musgrave | 703835c | 2015-09-16 00:38:22 +0000 | [diff] [blame] | 1846 | EHStack.pushCleanup<SanitizeDtorMembers>(NormalAndEHCleanup, DD); | 
| Naomi Musgrave | 866af2d | 2015-09-03 23:02:30 +0000 | [diff] [blame] | 1847 |  | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1848 | // Destroy direct fields. | 
| Aaron Ballman | e8a8bae | 2014-03-08 20:12:42 +0000 | [diff] [blame] | 1849 | for (const auto *Field : ClassDecl->fields()) { | 
|  | 1850 | QualType type = Field->getType(); | 
| John McCall | 4bd0fb1 | 2011-07-12 16:41:08 +0000 | [diff] [blame] | 1851 | QualType::DestructionKind dtorKind = type.isDestructedType(); | 
|  | 1852 | if (!dtorKind) continue; | 
| John McCall | f99a631 | 2010-07-21 05:30:47 +0000 | [diff] [blame] | 1853 |  | 
| Richard Smith | 921bd20 | 2012-02-26 09:11:52 +0000 | [diff] [blame] | 1854 | // Anonymous union members do not have their destructors called. | 
|  | 1855 | const RecordType *RT = type->getAsUnionType(); | 
|  | 1856 | if (RT && RT->getDecl()->isAnonymousStructOrUnion()) continue; | 
|  | 1857 |  | 
| John McCall | 4bd0fb1 | 2011-07-12 16:41:08 +0000 | [diff] [blame] | 1858 | CleanupKind cleanupKind = getCleanupKind(dtorKind); | 
| Aaron Ballman | e8a8bae | 2014-03-08 20:12:42 +0000 | [diff] [blame] | 1859 | EHStack.pushCleanup<DestroyField>(cleanupKind, Field, | 
| John McCall | 4bd0fb1 | 2011-07-12 16:41:08 +0000 | [diff] [blame] | 1860 | getDestroyer(dtorKind), | 
|  | 1861 | cleanupKind & EHCleanup); | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 1862 | } | 
| Anders Carlsson | fb40488 | 2009-12-24 22:46:43 +0000 | [diff] [blame] | 1863 | } | 
|  | 1864 |  | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1865 | /// EmitCXXAggrConstructorCall - Emit a loop to call a particular | 
|  | 1866 | /// constructor for each of several members of an array. | 
| Douglas Gregor | 05fc5be | 2010-07-21 01:10:17 +0000 | [diff] [blame] | 1867 | /// | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1868 | /// \param ctor the constructor to call for each element | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1869 | /// \param arrayType the type of the array to initialize | 
|  | 1870 | /// \param arrayBegin an arrayType* | 
|  | 1871 | /// \param zeroInitialize true if each element should be | 
|  | 1872 | ///   zero-initialized before it is constructed | 
| Alexey Samsonov | 70b9c01 | 2014-08-21 20:26:47 +0000 | [diff] [blame] | 1873 | void CodeGenFunction::EmitCXXAggrConstructorCall( | 
| Alexey Bataev | e7545b3 | 2016-04-29 09:39:50 +0000 | [diff] [blame] | 1874 | const CXXConstructorDecl *ctor, const ArrayType *arrayType, | 
| Serge Pavlov | 3760518 | 2018-07-28 15:33:03 +0000 | [diff] [blame] | 1875 | Address arrayBegin, const CXXConstructExpr *E, bool NewPointerIsChecked, | 
|  | 1876 | bool zeroInitialize) { | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1877 | QualType elementType; | 
|  | 1878 | llvm::Value *numElements = | 
|  | 1879 | emitArrayLength(arrayType, elementType, arrayBegin); | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 1880 |  | 
| Serge Pavlov | 3760518 | 2018-07-28 15:33:03 +0000 | [diff] [blame] | 1881 | EmitCXXAggrConstructorCall(ctor, numElements, arrayBegin, E, | 
|  | 1882 | NewPointerIsChecked, zeroInitialize); | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 1883 | } | 
|  | 1884 |  | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1885 | /// EmitCXXAggrConstructorCall - Emit a loop to call a particular | 
|  | 1886 | /// constructor for each of several members of an array. | 
|  | 1887 | /// | 
|  | 1888 | /// \param ctor the constructor to call for each element | 
|  | 1889 | /// \param numElements the number of elements in the array; | 
| John McCall | 6549b31 | 2011-07-13 07:37:11 +0000 | [diff] [blame] | 1890 | ///   may be zero | 
| NAKAMURA Takumi | ff7a925 | 2015-09-08 09:42:41 +0000 | [diff] [blame] | 1891 | /// \param arrayBase a T*, where T is the type constructed by ctor | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1892 | /// \param zeroInitialize true if each element should be | 
|  | 1893 | ///   zero-initialized before it is constructed | 
| Alexey Samsonov | 70b9c01 | 2014-08-21 20:26:47 +0000 | [diff] [blame] | 1894 | void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, | 
|  | 1895 | llvm::Value *numElements, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1896 | Address arrayBase, | 
| Alexey Samsonov | 70b9c01 | 2014-08-21 20:26:47 +0000 | [diff] [blame] | 1897 | const CXXConstructExpr *E, | 
| Serge Pavlov | 3760518 | 2018-07-28 15:33:03 +0000 | [diff] [blame] | 1898 | bool NewPointerIsChecked, | 
| Alexey Samsonov | 70b9c01 | 2014-08-21 20:26:47 +0000 | [diff] [blame] | 1899 | bool zeroInitialize) { | 
| John McCall | 6549b31 | 2011-07-13 07:37:11 +0000 | [diff] [blame] | 1900 | // It's legal for numElements to be zero.  This can happen both | 
|  | 1901 | // dynamically, because x can be zero in 'new A[x]', and statically, | 
|  | 1902 | // because of GCC extensions that permit zero-length arrays.  There | 
|  | 1903 | // are probably legitimate places where we could assume that this | 
|  | 1904 | // doesn't happen, but it's not clear that it's worth it. | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 1905 | llvm::BranchInst *zeroCheckBranch = nullptr; | 
| John McCall | 6549b31 | 2011-07-13 07:37:11 +0000 | [diff] [blame] | 1906 |  | 
|  | 1907 | // Optimize for a constant count. | 
|  | 1908 | llvm::ConstantInt *constantCount | 
|  | 1909 | = dyn_cast<llvm::ConstantInt>(numElements); | 
|  | 1910 | if (constantCount) { | 
|  | 1911 | // Just skip out if the constant count is zero. | 
|  | 1912 | if (constantCount->isZero()) return; | 
|  | 1913 |  | 
|  | 1914 | // Otherwise, emit the check. | 
|  | 1915 | } else { | 
|  | 1916 | llvm::BasicBlock *loopBB = createBasicBlock("new.ctorloop"); | 
|  | 1917 | llvm::Value *iszero = Builder.CreateIsNull(numElements, "isempty"); | 
|  | 1918 | zeroCheckBranch = Builder.CreateCondBr(iszero, loopBB, loopBB); | 
|  | 1919 | EmitBlock(loopBB); | 
|  | 1920 | } | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1921 |  | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1922 | // Find the end of the array. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1923 | llvm::Value *arrayBegin = arrayBase.getPointer(); | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1924 | llvm::Value *arrayEnd = Builder.CreateInBoundsGEP(arrayBegin, numElements, | 
|  | 1925 | "arrayctor.end"); | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 1926 |  | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1927 | // Enter the loop, setting up a phi for the current location to initialize. | 
|  | 1928 | llvm::BasicBlock *entryBB = Builder.GetInsertBlock(); | 
|  | 1929 | llvm::BasicBlock *loopBB = createBasicBlock("arrayctor.loop"); | 
|  | 1930 | EmitBlock(loopBB); | 
|  | 1931 | llvm::PHINode *cur = Builder.CreatePHI(arrayBegin->getType(), 2, | 
|  | 1932 | "arrayctor.cur"); | 
|  | 1933 | cur->addIncoming(arrayBegin, entryBB); | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 1934 |  | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 1935 | // Inside the loop body, emit the constructor call on the array element. | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1936 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1937 | // The alignment of the base, adjusted by the size of a single element, | 
|  | 1938 | // provides a conservative estimate of the alignment of every element. | 
|  | 1939 | // (This assumes we never start tracking offsetted alignments.) | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 1940 | // | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1941 | // Note that these are complete objects and so we don't need to | 
|  | 1942 | // use the non-virtual size or alignment. | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1943 | QualType type = getContext().getTypeDeclType(ctor->getParent()); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1944 | CharUnits eltAlignment = | 
|  | 1945 | arrayBase.getAlignment() | 
|  | 1946 | .alignmentOfArrayElement(getContext().getTypeSizeInChars(type)); | 
|  | 1947 | Address curAddr = Address(cur, eltAlignment); | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 1948 |  | 
| Douglas Gregor | 05fc5be | 2010-07-21 01:10:17 +0000 | [diff] [blame] | 1949 | // Zero initialize the storage, if requested. | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1950 | if (zeroInitialize) | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1951 | EmitNullInitialization(curAddr, type); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1952 |  | 
|  | 1953 | // C++ [class.temporary]p4: | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 1954 | // There are two contexts in which temporaries are destroyed at a different | 
|  | 1955 | // point than the end of the full-expression. The first context is when a | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1956 | // default constructor is called to initialize an element of an array. | 
|  | 1957 | // If the constructor has one or more default arguments, the destruction of | 
|  | 1958 | // every temporary created in a default argument expression is sequenced | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 1959 | // before the construction of the next array element, if any. | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 1960 |  | 
| Anders Carlsson | b9fd57f | 2010-03-30 03:14:41 +0000 | [diff] [blame] | 1961 | { | 
| John McCall | bd30929 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1962 | RunCleanupsScope Scope(*this); | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 1963 |  | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1964 | // Evaluate the constructor and its arguments in a regular | 
|  | 1965 | // partial-destroy cleanup. | 
| David Blaikie | bbafb8a | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 1966 | if (getLangOpts().Exceptions && | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1967 | !ctor->getParent()->hasTrivialDestructor()) { | 
|  | 1968 | Destroyer *destroyer = destroyCXXObject; | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1969 | pushRegularPartialArrayCleanup(arrayBegin, cur, type, eltAlignment, | 
|  | 1970 | *destroyer); | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1971 | } | 
|  | 1972 |  | 
| Alexey Samsonov | 70b9c01 | 2014-08-21 20:26:47 +0000 | [diff] [blame] | 1973 | EmitCXXConstructorCall(ctor, Ctor_Complete, /*ForVirtualBase=*/false, | 
| Richard Smith | e78fac5 | 2018-04-05 20:52:58 +0000 | [diff] [blame] | 1974 | /*Delegating=*/false, curAddr, E, | 
| Serge Pavlov | 3760518 | 2018-07-28 15:33:03 +0000 | [diff] [blame] | 1975 | AggValueSlot::DoesNotOverlap, NewPointerIsChecked); | 
| Anders Carlsson | b9fd57f | 2010-03-30 03:14:41 +0000 | [diff] [blame] | 1976 | } | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 1977 |  | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1978 | // Go to the next element. | 
|  | 1979 | llvm::Value *next = | 
|  | 1980 | Builder.CreateInBoundsGEP(cur, llvm::ConstantInt::get(SizeTy, 1), | 
|  | 1981 | "arrayctor.next"); | 
|  | 1982 | cur->addIncoming(next, Builder.GetInsertBlock()); | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 1983 |  | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1984 | // Check whether that's the end of the loop. | 
|  | 1985 | llvm::Value *done = Builder.CreateICmpEQ(next, arrayEnd, "arrayctor.done"); | 
|  | 1986 | llvm::BasicBlock *contBB = createBasicBlock("arrayctor.cont"); | 
|  | 1987 | Builder.CreateCondBr(done, contBB, loopBB); | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 1988 |  | 
| John McCall | 6549b31 | 2011-07-13 07:37:11 +0000 | [diff] [blame] | 1989 | // Patch the earlier check to skip over the loop. | 
|  | 1990 | if (zeroCheckBranch) zeroCheckBranch->setSuccessor(0, contBB); | 
|  | 1991 |  | 
| John McCall | f677a8e | 2011-07-13 06:10:41 +0000 | [diff] [blame] | 1992 | EmitBlock(contBB); | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 1993 | } | 
|  | 1994 |  | 
| John McCall | 82fe67b | 2011-07-09 01:37:26 +0000 | [diff] [blame] | 1995 | void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 1996 | Address addr, | 
| John McCall | 82fe67b | 2011-07-09 01:37:26 +0000 | [diff] [blame] | 1997 | QualType type) { | 
|  | 1998 | const RecordType *rtype = type->castAs<RecordType>(); | 
|  | 1999 | const CXXRecordDecl *record = cast<CXXRecordDecl>(rtype->getDecl()); | 
|  | 2000 | const CXXDestructorDecl *dtor = record->getDestructor(); | 
|  | 2001 | assert(!dtor->isTrivial()); | 
|  | 2002 | CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*for vbase*/ false, | 
| Douglas Gregor | 6153500 | 2013-01-31 05:50:40 +0000 | [diff] [blame] | 2003 | /*Delegating=*/false, addr); | 
| John McCall | 82fe67b | 2011-07-09 01:37:26 +0000 | [diff] [blame] | 2004 | } | 
|  | 2005 |  | 
| Alexey Samsonov | 70b9c01 | 2014-08-21 20:26:47 +0000 | [diff] [blame] | 2006 | void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, | 
|  | 2007 | CXXCtorType Type, | 
|  | 2008 | bool ForVirtualBase, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2009 | bool Delegating, Address This, | 
| Richard Smith | e78fac5 | 2018-04-05 20:52:58 +0000 | [diff] [blame] | 2010 | const CXXConstructExpr *E, | 
| Serge Pavlov | 3760518 | 2018-07-28 15:33:03 +0000 | [diff] [blame] | 2011 | AggValueSlot::Overlap_t Overlap, | 
|  | 2012 | bool NewPointerIsChecked) { | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2013 | CallArgList Args; | 
|  | 2014 |  | 
|  | 2015 | // Push the this ptr. | 
|  | 2016 | Args.add(RValue::get(This.getPointer()), D->getThisType(getContext())); | 
|  | 2017 |  | 
|  | 2018 | // If this is a trivial constructor, emit a memcpy now before we lose | 
|  | 2019 | // the alignment information on the argument. | 
|  | 2020 | // FIXME: It would be better to preserve alignment information into CallArg. | 
|  | 2021 | if (isMemcpyEquivalentSpecialMember(D)) { | 
|  | 2022 | assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor"); | 
|  | 2023 |  | 
|  | 2024 | const Expr *Arg = E->getArg(0); | 
| Ivan A. Kosarev | 1860b52 | 2018-01-25 14:21:55 +0000 | [diff] [blame] | 2025 | LValue Src = EmitLValue(Arg); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2026 | QualType DestTy = getContext().getTypeDeclType(D->getParent()); | 
| Ivan A. Kosarev | 1860b52 | 2018-01-25 14:21:55 +0000 | [diff] [blame] | 2027 | LValue Dest = MakeAddrLValue(This, DestTy); | 
| Richard Smith | e78fac5 | 2018-04-05 20:52:58 +0000 | [diff] [blame] | 2028 | EmitAggregateCopyCtor(Dest, Src, Overlap); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2029 | return; | 
|  | 2030 | } | 
|  | 2031 |  | 
|  | 2032 | // Add the rest of the user-supplied arguments. | 
|  | 2033 | const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>(); | 
| Hans Wennborg | 27dcc6c | 2017-02-01 02:21:07 +0000 | [diff] [blame] | 2034 | EvaluationOrder Order = E->isListInitialization() | 
|  | 2035 | ? EvaluationOrder::ForceLeftToRight | 
|  | 2036 | : EvaluationOrder::Default; | 
|  | 2037 | EmitCallArgs(Args, FPT, E->arguments(), E->getConstructor(), | 
|  | 2038 | /*ParamsToSkip*/ 0, Order); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2039 |  | 
| Richard Smith | e78fac5 | 2018-04-05 20:52:58 +0000 | [diff] [blame] | 2040 | EmitCXXConstructorCall(D, Type, ForVirtualBase, Delegating, This, Args, | 
| Serge Pavlov | 3760518 | 2018-07-28 15:33:03 +0000 | [diff] [blame] | 2041 | Overlap, E->getExprLoc(), NewPointerIsChecked); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2042 | } | 
|  | 2043 |  | 
|  | 2044 | static bool canEmitDelegateCallArgs(CodeGenFunction &CGF, | 
|  | 2045 | const CXXConstructorDecl *Ctor, | 
|  | 2046 | CXXCtorType Type, CallArgList &Args) { | 
|  | 2047 | // We can't forward a variadic call. | 
|  | 2048 | if (Ctor->isVariadic()) | 
|  | 2049 | return false; | 
|  | 2050 |  | 
|  | 2051 | if (CGF.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) { | 
|  | 2052 | // If the parameters are callee-cleanup, it's not safe to forward. | 
|  | 2053 | for (auto *P : Ctor->parameters()) | 
|  | 2054 | if (P->getType().isDestructedType()) | 
|  | 2055 | return false; | 
|  | 2056 |  | 
|  | 2057 | // Likewise if they're inalloca. | 
|  | 2058 | const CGFunctionInfo &Info = | 
| George Burgess IV | d0a9e80 | 2017-02-23 22:07:35 +0000 | [diff] [blame] | 2059 | CGF.CGM.getTypes().arrangeCXXConstructorCall(Args, Ctor, Type, 0, 0); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2060 | if (Info.usesInAlloca()) | 
|  | 2061 | return false; | 
|  | 2062 | } | 
|  | 2063 |  | 
|  | 2064 | // Anything else should be OK. | 
|  | 2065 | return true; | 
|  | 2066 | } | 
|  | 2067 |  | 
|  | 2068 | void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, | 
|  | 2069 | CXXCtorType Type, | 
|  | 2070 | bool ForVirtualBase, | 
|  | 2071 | bool Delegating, | 
|  | 2072 | Address This, | 
| Richard Smith | e78fac5 | 2018-04-05 20:52:58 +0000 | [diff] [blame] | 2073 | CallArgList &Args, | 
| Igor Kudrin | eff8f9d | 2018-06-25 05:48:04 +0000 | [diff] [blame] | 2074 | AggValueSlot::Overlap_t Overlap, | 
| Serge Pavlov | 3760518 | 2018-07-28 15:33:03 +0000 | [diff] [blame] | 2075 | SourceLocation Loc, | 
|  | 2076 | bool NewPointerIsChecked) { | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2077 | const CXXRecordDecl *ClassDecl = D->getParent(); | 
|  | 2078 |  | 
| Serge Pavlov | 3760518 | 2018-07-28 15:33:03 +0000 | [diff] [blame] | 2079 | if (!NewPointerIsChecked) | 
|  | 2080 | EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This.getPointer(), | 
|  | 2081 | getContext().getRecordType(ClassDecl), CharUnits::Zero()); | 
| John McCall | ca972cd | 2010-02-06 00:25:16 +0000 | [diff] [blame] | 2082 |  | 
| Richard Smith | 419bd09 | 2015-04-29 19:26:57 +0000 | [diff] [blame] | 2083 | if (D->isTrivial() && D->isDefaultConstructor()) { | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2084 | assert(Args.size() == 1 && "trivial default ctor with args"); | 
| Richard Smith | 419bd09 | 2015-04-29 19:26:57 +0000 | [diff] [blame] | 2085 | return; | 
|  | 2086 | } | 
|  | 2087 |  | 
|  | 2088 | // If this is a trivial constructor, just emit what's needed. If this is a | 
|  | 2089 | // union copy constructor, we must emit a memcpy, because the AST does not | 
|  | 2090 | // model that copy. | 
|  | 2091 | if (isMemcpyEquivalentSpecialMember(D)) { | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2092 | assert(Args.size() == 2 && "unexpected argcount for trivial ctor"); | 
| John McCall | ca972cd | 2010-02-06 00:25:16 +0000 | [diff] [blame] | 2093 |  | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2094 | QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType(); | 
| Yaxun Liu | 5b330e8 | 2018-03-15 15:25:19 +0000 | [diff] [blame] | 2095 | Address Src(Args[1].getRValue(*this).getScalarVal(), | 
|  | 2096 | getNaturalTypeAlignment(SrcTy)); | 
| Ivan A. Kosarev | 1860b52 | 2018-01-25 14:21:55 +0000 | [diff] [blame] | 2097 | LValue SrcLVal = MakeAddrLValue(Src, SrcTy); | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2098 | QualType DestTy = getContext().getTypeDeclType(ClassDecl); | 
| Ivan A. Kosarev | 1860b52 | 2018-01-25 14:21:55 +0000 | [diff] [blame] | 2099 | LValue DestLVal = MakeAddrLValue(This, DestTy); | 
| Richard Smith | e78fac5 | 2018-04-05 20:52:58 +0000 | [diff] [blame] | 2100 | EmitAggregateCopyCtor(DestLVal, SrcLVal, Overlap); | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 2101 | return; | 
|  | 2102 | } | 
|  | 2103 |  | 
| George Burgess IV | d0a9e80 | 2017-02-23 22:07:35 +0000 | [diff] [blame] | 2104 | bool PassPrototypeArgs = true; | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2105 | // Check whether we can actually emit the constructor before trying to do so. | 
|  | 2106 | if (auto Inherited = D->getInheritedConstructor()) { | 
| George Burgess IV | d0a9e80 | 2017-02-23 22:07:35 +0000 | [diff] [blame] | 2107 | PassPrototypeArgs = getTypes().inheritingCtorHasParams(Inherited, Type); | 
|  | 2108 | if (PassPrototypeArgs && !canEmitDelegateCallArgs(*this, D, Type, Args)) { | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2109 | EmitInlinedInheritingCXXConstructorCall(D, Type, ForVirtualBase, | 
|  | 2110 | Delegating, Args); | 
|  | 2111 | return; | 
|  | 2112 | } | 
|  | 2113 | } | 
| Reid Kleckner | 89077a1 | 2013-12-17 19:46:40 +0000 | [diff] [blame] | 2114 |  | 
|  | 2115 | // Insert any ABI-specific implicit constructor arguments. | 
| George Burgess IV | f203dbf | 2017-02-22 20:28:02 +0000 | [diff] [blame] | 2116 | CGCXXABI::AddedStructorArgs ExtraArgs = | 
|  | 2117 | CGM.getCXXABI().addImplicitConstructorArgs(*this, D, Type, ForVirtualBase, | 
|  | 2118 | Delegating, Args); | 
| Reid Kleckner | 89077a1 | 2013-12-17 19:46:40 +0000 | [diff] [blame] | 2119 |  | 
|  | 2120 | // Emit the call. | 
| John McCall | b92ab1a | 2016-10-26 23:46:34 +0000 | [diff] [blame] | 2121 | llvm::Constant *CalleePtr = | 
|  | 2122 | CGM.getAddrOfCXXStructor(D, getFromCtorType(Type)); | 
| George Burgess IV | f203dbf | 2017-02-22 20:28:02 +0000 | [diff] [blame] | 2123 | const CGFunctionInfo &Info = CGM.getTypes().arrangeCXXConstructorCall( | 
| George Burgess IV | d0a9e80 | 2017-02-23 22:07:35 +0000 | [diff] [blame] | 2124 | Args, D, Type, ExtraArgs.Prefix, ExtraArgs.Suffix, PassPrototypeArgs); | 
| John McCall | b92ab1a | 2016-10-26 23:46:34 +0000 | [diff] [blame] | 2125 | CGCallee Callee = CGCallee::forDirect(CalleePtr, D); | 
|  | 2126 | EmitCall(Info, Callee, ReturnValueSlot(), Args); | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2127 |  | 
|  | 2128 | // Generate vtable assumptions if we're constructing a complete object | 
|  | 2129 | // with a vtable.  We don't do this for base subobjects for two reasons: | 
|  | 2130 | // first, it's incorrect for classes with virtual bases, and second, we're | 
|  | 2131 | // about to overwrite the vptrs anyway. | 
|  | 2132 | // We also have to make sure if we can refer to vtable: | 
|  | 2133 | // - Otherwise we can refer to vtable if it's safe to speculatively emit. | 
|  | 2134 | // FIXME: If vtable is used by ctor/dtor, or if vtable is external and we are | 
|  | 2135 | // sure that definition of vtable is not hidden, | 
|  | 2136 | // then we are always safe to refer to it. | 
| Piotr Padlewski | 69dc971 | 2015-09-28 20:30:22 +0000 | [diff] [blame] | 2137 | // FIXME: It looks like InstCombine is very inefficient on dealing with | 
|  | 2138 | // assumes. Make assumption loads require -fstrict-vtable-pointers temporarily. | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2139 | if (CGM.getCodeGenOpts().OptimizationLevel > 0 && | 
|  | 2140 | ClassDecl->isDynamicClass() && Type != Ctor_Base && | 
| Piotr Padlewski | 69dc971 | 2015-09-28 20:30:22 +0000 | [diff] [blame] | 2141 | CGM.getCXXABI().canSpeculativelyEmitVTable(ClassDecl) && | 
|  | 2142 | CGM.getCodeGenOpts().StrictVTablePointers) | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2143 | EmitVTableAssumptionLoads(ClassDecl, This); | 
|  | 2144 | } | 
|  | 2145 |  | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2146 | void CodeGenFunction::EmitInheritedCXXConstructorCall( | 
|  | 2147 | const CXXConstructorDecl *D, bool ForVirtualBase, Address This, | 
|  | 2148 | bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) { | 
|  | 2149 | CallArgList Args; | 
| Yaxun Liu | 5b330e8 | 2018-03-15 15:25:19 +0000 | [diff] [blame] | 2150 | CallArg ThisArg(RValue::get(This.getPointer()), D->getThisType(getContext())); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2151 |  | 
|  | 2152 | // Forward the parameters. | 
|  | 2153 | if (InheritedFromVBase && | 
|  | 2154 | CGM.getTarget().getCXXABI().hasConstructorVariants()) { | 
|  | 2155 | // Nothing to do; this construction is not responsible for constructing | 
|  | 2156 | // the base class containing the inherited constructor. | 
|  | 2157 | // FIXME: Can we just pass undef's for the remaining arguments if we don't | 
|  | 2158 | // have constructor variants? | 
|  | 2159 | Args.push_back(ThisArg); | 
|  | 2160 | } else if (!CXXInheritedCtorInitExprArgs.empty()) { | 
|  | 2161 | // The inheriting constructor was inlined; just inject its arguments. | 
|  | 2162 | assert(CXXInheritedCtorInitExprArgs.size() >= D->getNumParams() && | 
|  | 2163 | "wrong number of parameters for inherited constructor call"); | 
|  | 2164 | Args = CXXInheritedCtorInitExprArgs; | 
|  | 2165 | Args[0] = ThisArg; | 
|  | 2166 | } else { | 
|  | 2167 | // The inheriting constructor was not inlined. Emit delegating arguments. | 
|  | 2168 | Args.push_back(ThisArg); | 
|  | 2169 | const auto *OuterCtor = cast<CXXConstructorDecl>(CurCodeDecl); | 
|  | 2170 | assert(OuterCtor->getNumParams() == D->getNumParams()); | 
|  | 2171 | assert(!OuterCtor->isVariadic() && "should have been inlined"); | 
|  | 2172 |  | 
|  | 2173 | for (const auto *Param : OuterCtor->parameters()) { | 
|  | 2174 | assert(getContext().hasSameUnqualifiedType( | 
|  | 2175 | OuterCtor->getParamDecl(Param->getFunctionScopeIndex())->getType(), | 
|  | 2176 | Param->getType())); | 
|  | 2177 | EmitDelegateCallArg(Args, Param, E->getLocation()); | 
|  | 2178 |  | 
|  | 2179 | // Forward __attribute__(pass_object_size). | 
|  | 2180 | if (Param->hasAttr<PassObjectSizeAttr>()) { | 
|  | 2181 | auto *POSParam = SizeArguments[Param]; | 
|  | 2182 | assert(POSParam && "missing pass_object_size value for forwarding"); | 
|  | 2183 | EmitDelegateCallArg(Args, POSParam, E->getLocation()); | 
|  | 2184 | } | 
|  | 2185 | } | 
|  | 2186 | } | 
|  | 2187 |  | 
|  | 2188 | EmitCXXConstructorCall(D, Ctor_Base, ForVirtualBase, /*Delegating*/false, | 
| Igor Kudrin | eff8f9d | 2018-06-25 05:48:04 +0000 | [diff] [blame] | 2189 | This, Args, AggValueSlot::MayOverlap, | 
| Serge Pavlov | 3760518 | 2018-07-28 15:33:03 +0000 | [diff] [blame] | 2190 | E->getLocation(), /*NewPointerIsChecked*/true); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2191 | } | 
|  | 2192 |  | 
|  | 2193 | void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall( | 
|  | 2194 | const CXXConstructorDecl *Ctor, CXXCtorType CtorType, bool ForVirtualBase, | 
|  | 2195 | bool Delegating, CallArgList &Args) { | 
| Adrian Prantl | b7acfc0 | 2017-02-27 21:30:05 +0000 | [diff] [blame] | 2196 | GlobalDecl GD(Ctor, CtorType); | 
|  | 2197 | InlinedInheritingConstructorScope Scope(*this, GD); | 
|  | 2198 | ApplyInlineDebugLocation DebugScope(*this, GD); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2199 |  | 
|  | 2200 | // Save the arguments to be passed to the inherited constructor. | 
|  | 2201 | CXXInheritedCtorInitExprArgs = Args; | 
|  | 2202 |  | 
|  | 2203 | FunctionArgList Params; | 
|  | 2204 | QualType RetType = BuildFunctionArgList(CurGD, Params); | 
|  | 2205 | FnRetTy = RetType; | 
|  | 2206 |  | 
|  | 2207 | // Insert any ABI-specific implicit constructor arguments. | 
|  | 2208 | CGM.getCXXABI().addImplicitConstructorArgs(*this, Ctor, CtorType, | 
|  | 2209 | ForVirtualBase, Delegating, Args); | 
|  | 2210 |  | 
|  | 2211 | // Emit a simplified prolog. We only need to emit the implicit params. | 
|  | 2212 | assert(Args.size() >= Params.size() && "too few arguments for call"); | 
|  | 2213 | for (unsigned I = 0, N = Args.size(); I != N; ++I) { | 
|  | 2214 | if (I < Params.size() && isa<ImplicitParamDecl>(Params[I])) { | 
| Yaxun Liu | 5b330e8 | 2018-03-15 15:25:19 +0000 | [diff] [blame] | 2215 | const RValue &RV = Args[I].getRValue(*this); | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2216 | assert(!RV.isComplex() && "complex indirect params not supported"); | 
|  | 2217 | ParamValue Val = RV.isScalar() | 
|  | 2218 | ? ParamValue::forDirect(RV.getScalarVal()) | 
|  | 2219 | : ParamValue::forIndirect(RV.getAggregateAddress()); | 
|  | 2220 | EmitParmDecl(*Params[I], Val, I + 1); | 
|  | 2221 | } | 
|  | 2222 | } | 
|  | 2223 |  | 
|  | 2224 | // Create a return value slot if the ABI implementation wants one. | 
|  | 2225 | // FIXME: This is dumb, we should ask the ABI not to try to set the return | 
|  | 2226 | // value instead. | 
|  | 2227 | if (!RetType->isVoidType()) | 
|  | 2228 | ReturnValue = CreateIRTemp(RetType, "retval.inhctor"); | 
|  | 2229 |  | 
|  | 2230 | CGM.getCXXABI().EmitInstanceFunctionProlog(*this); | 
|  | 2231 | CXXThisValue = CXXABIThisValue; | 
|  | 2232 |  | 
|  | 2233 | // Directly emit the constructor initializers. | 
|  | 2234 | EmitCtorPrologue(Ctor, CtorType, Params); | 
|  | 2235 | } | 
|  | 2236 |  | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2237 | void CodeGenFunction::EmitVTableAssumptionLoad(const VPtr &Vptr, Address This) { | 
|  | 2238 | llvm::Value *VTableGlobal = | 
|  | 2239 | CGM.getCXXABI().getVTableAddressPoint(Vptr.Base, Vptr.VTableClass); | 
|  | 2240 | if (!VTableGlobal) | 
|  | 2241 | return; | 
|  | 2242 |  | 
|  | 2243 | // We can just use the base offset in the complete class. | 
|  | 2244 | CharUnits NonVirtualOffset = Vptr.Base.getBaseOffset(); | 
|  | 2245 |  | 
|  | 2246 | if (!NonVirtualOffset.isZero()) | 
|  | 2247 | This = | 
|  | 2248 | ApplyNonVirtualAndVirtualOffset(*this, This, NonVirtualOffset, nullptr, | 
|  | 2249 | Vptr.VTableClass, Vptr.NearestVBase); | 
|  | 2250 |  | 
| Piotr Padlewski | 4b1ac72 | 2015-09-15 21:46:55 +0000 | [diff] [blame] | 2251 | llvm::Value *VPtrValue = | 
|  | 2252 | GetVTablePtr(This, VTableGlobal->getType(), Vptr.VTableClass); | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2253 | llvm::Value *Cmp = | 
|  | 2254 | Builder.CreateICmpEQ(VPtrValue, VTableGlobal, "cmp.vtables"); | 
|  | 2255 | Builder.CreateAssumption(Cmp); | 
|  | 2256 | } | 
|  | 2257 |  | 
|  | 2258 | void CodeGenFunction::EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl, | 
|  | 2259 | Address This) { | 
|  | 2260 | if (CGM.getCXXABI().doStructorsInitializeVPtrs(ClassDecl)) | 
|  | 2261 | for (const VPtr &Vptr : getVTablePointers(ClassDecl)) | 
|  | 2262 | EmitVTableAssumptionLoad(Vptr, This); | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 2263 | } | 
|  | 2264 |  | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 2265 | void | 
| Fariborz Jahanian | e988bda | 2010-11-13 21:53:34 +0000 | [diff] [blame] | 2266 | CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2267 | Address This, Address Src, | 
|  | 2268 | const CXXConstructExpr *E) { | 
| Reid Kleckner | 739756c | 2013-12-04 19:23:12 +0000 | [diff] [blame] | 2269 | const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>(); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 2270 |  | 
| Fariborz Jahanian | e988bda | 2010-11-13 21:53:34 +0000 | [diff] [blame] | 2271 | CallArgList Args; | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 2272 |  | 
| Fariborz Jahanian | e988bda | 2010-11-13 21:53:34 +0000 | [diff] [blame] | 2273 | // Push the this ptr. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2274 | Args.add(RValue::get(This.getPointer()), D->getThisType(getContext())); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 2275 |  | 
| Fariborz Jahanian | e988bda | 2010-11-13 21:53:34 +0000 | [diff] [blame] | 2276 | // Push the src ptr. | 
| Alp Toker | 9cacbab | 2014-01-20 20:26:09 +0000 | [diff] [blame] | 2277 | QualType QT = *(FPT->param_type_begin()); | 
| Chris Lattner | 2192fe5 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 2278 | llvm::Type *t = CGM.getTypes().ConvertType(QT); | 
| Fariborz Jahanian | e988bda | 2010-11-13 21:53:34 +0000 | [diff] [blame] | 2279 | Src = Builder.CreateBitCast(Src, t); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2280 | Args.add(RValue::get(Src.getPointer()), QT); | 
| Reid Kleckner | 739756c | 2013-12-04 19:23:12 +0000 | [diff] [blame] | 2281 |  | 
| Fariborz Jahanian | e988bda | 2010-11-13 21:53:34 +0000 | [diff] [blame] | 2282 | // Skip over first argument (Src). | 
| David Blaikie | f05779e | 2015-07-21 18:37:18 +0000 | [diff] [blame] | 2283 | EmitCallArgs(Args, FPT, drop_begin(E->arguments(), 1), E->getConstructor(), | 
| Alexey Samsonov | 8e1162c | 2014-09-08 17:22:45 +0000 | [diff] [blame] | 2284 | /*ParamsToSkip*/ 1); | 
| Reid Kleckner | 739756c | 2013-12-04 19:23:12 +0000 | [diff] [blame] | 2285 |  | 
| Serge Pavlov | 3760518 | 2018-07-28 15:33:03 +0000 | [diff] [blame] | 2286 | EmitCXXConstructorCall(D, Ctor_Complete, /*ForVirtualBase*/false, | 
|  | 2287 | /*Delegating*/false, This, Args, | 
|  | 2288 | AggValueSlot::MayOverlap, E->getExprLoc(), | 
|  | 2289 | /*NewPointerIsChecked*/false); | 
| Fariborz Jahanian | e988bda | 2010-11-13 21:53:34 +0000 | [diff] [blame] | 2290 | } | 
|  | 2291 |  | 
|  | 2292 | void | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 2293 | CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, | 
|  | 2294 | CXXCtorType CtorType, | 
| Nick Lewycky | 2d84e84 | 2013-10-02 02:29:49 +0000 | [diff] [blame] | 2295 | const FunctionArgList &Args, | 
|  | 2296 | SourceLocation Loc) { | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 2297 | CallArgList DelegateArgs; | 
|  | 2298 |  | 
|  | 2299 | FunctionArgList::const_iterator I = Args.begin(), E = Args.end(); | 
|  | 2300 | assert(I != E && "no parameters to constructor"); | 
|  | 2301 |  | 
|  | 2302 | // this | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2303 | Address This = LoadCXXThisAddress(); | 
|  | 2304 | DelegateArgs.add(RValue::get(This.getPointer()), (*I)->getType()); | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 2305 | ++I; | 
|  | 2306 |  | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2307 | // FIXME: The location of the VTT parameter in the parameter list is | 
|  | 2308 | // specific to the Itanium ABI and shouldn't be hardcoded here. | 
|  | 2309 | if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) { | 
|  | 2310 | assert(I != E && "cannot skip vtt parameter, already done with args"); | 
|  | 2311 | assert((*I)->getType()->isPointerType() && | 
|  | 2312 | "skipping parameter not of vtt type"); | 
|  | 2313 | ++I; | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 2314 | } | 
|  | 2315 |  | 
|  | 2316 | // Explicit arguments. | 
|  | 2317 | for (; I != E; ++I) { | 
| John McCall | 32ea969 | 2011-03-11 20:59:21 +0000 | [diff] [blame] | 2318 | const VarDecl *param = *I; | 
| Nick Lewycky | 2d84e84 | 2013-10-02 02:29:49 +0000 | [diff] [blame] | 2319 | // FIXME: per-argument source location | 
|  | 2320 | EmitDelegateCallArg(DelegateArgs, param, Loc); | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 2321 | } | 
|  | 2322 |  | 
| Richard Smith | 5179eb7 | 2016-06-28 19:03:57 +0000 | [diff] [blame] | 2323 | EmitCXXConstructorCall(Ctor, CtorType, /*ForVirtualBase=*/false, | 
| Richard Smith | e78fac5 | 2018-04-05 20:52:58 +0000 | [diff] [blame] | 2324 | /*Delegating=*/true, This, DelegateArgs, | 
| Serge Pavlov | 3760518 | 2018-07-28 15:33:03 +0000 | [diff] [blame] | 2325 | AggValueSlot::MayOverlap, Loc, | 
|  | 2326 | /*NewPointerIsChecked=*/true); | 
| John McCall | f8ff7b9 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 2327 | } | 
|  | 2328 |  | 
| Alexis Hunt | 9d47faf | 2011-05-03 23:05:34 +0000 | [diff] [blame] | 2329 | namespace { | 
| David Blaikie | 7e70d68 | 2015-08-18 22:40:54 +0000 | [diff] [blame] | 2330 | struct CallDelegatingCtorDtor final : EHScopeStack::Cleanup { | 
| Alexis Hunt | 9d47faf | 2011-05-03 23:05:34 +0000 | [diff] [blame] | 2331 | const CXXDestructorDecl *Dtor; | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2332 | Address Addr; | 
| Alexis Hunt | 9d47faf | 2011-05-03 23:05:34 +0000 | [diff] [blame] | 2333 | CXXDtorType Type; | 
|  | 2334 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2335 | CallDelegatingCtorDtor(const CXXDestructorDecl *D, Address Addr, | 
| Alexis Hunt | 9d47faf | 2011-05-03 23:05:34 +0000 | [diff] [blame] | 2336 | CXXDtorType Type) | 
|  | 2337 | : Dtor(D), Addr(Addr), Type(Type) {} | 
|  | 2338 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 2339 | void Emit(CodeGenFunction &CGF, Flags flags) override { | 
| Alexis Hunt | 9d47faf | 2011-05-03 23:05:34 +0000 | [diff] [blame] | 2340 | CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false, | 
| Douglas Gregor | 6153500 | 2013-01-31 05:50:40 +0000 | [diff] [blame] | 2341 | /*Delegating=*/true, Addr); | 
| Alexis Hunt | 9d47faf | 2011-05-03 23:05:34 +0000 | [diff] [blame] | 2342 | } | 
|  | 2343 | }; | 
| Hans Wennborg | dcfba33 | 2015-10-06 23:40:43 +0000 | [diff] [blame] | 2344 | } // end anonymous namespace | 
| Alexis Hunt | 9d47faf | 2011-05-03 23:05:34 +0000 | [diff] [blame] | 2345 |  | 
| Alexis Hunt | 61bc173 | 2011-05-01 07:04:31 +0000 | [diff] [blame] | 2346 | void | 
|  | 2347 | CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor, | 
|  | 2348 | const FunctionArgList &Args) { | 
|  | 2349 | assert(Ctor->isDelegatingConstructor()); | 
|  | 2350 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2351 | Address ThisPtr = LoadCXXThisAddress(); | 
| Alexis Hunt | 61bc173 | 2011-05-01 07:04:31 +0000 | [diff] [blame] | 2352 |  | 
| John McCall | 31168b0 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 2353 | AggValueSlot AggSlot = | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2354 | AggValueSlot::forAddr(ThisPtr, Qualifiers(), | 
| John McCall | 8d6fc95 | 2011-08-25 20:40:09 +0000 | [diff] [blame] | 2355 | AggValueSlot::IsDestructed, | 
| John McCall | a5efa73 | 2011-08-25 23:04:34 +0000 | [diff] [blame] | 2356 | AggValueSlot::DoesNotNeedGCBarriers, | 
| Richard Smith | e78fac5 | 2018-04-05 20:52:58 +0000 | [diff] [blame] | 2357 | AggValueSlot::IsNotAliased, | 
| Serge Pavlov | 3760518 | 2018-07-28 15:33:03 +0000 | [diff] [blame] | 2358 | AggValueSlot::MayOverlap, | 
|  | 2359 | AggValueSlot::IsNotZeroed, | 
|  | 2360 | // Checks are made by the code that calls constructor. | 
|  | 2361 | AggValueSlot::IsSanitizerChecked); | 
| Alexis Hunt | 61bc173 | 2011-05-01 07:04:31 +0000 | [diff] [blame] | 2362 |  | 
|  | 2363 | EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot); | 
| Alexis Hunt | 61bc173 | 2011-05-01 07:04:31 +0000 | [diff] [blame] | 2364 |  | 
| Alexis Hunt | 9d47faf | 2011-05-03 23:05:34 +0000 | [diff] [blame] | 2365 | const CXXRecordDecl *ClassDecl = Ctor->getParent(); | 
| David Blaikie | bbafb8a | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 2366 | if (CGM.getLangOpts().Exceptions && !ClassDecl->hasTrivialDestructor()) { | 
| Alexis Hunt | 9d47faf | 2011-05-03 23:05:34 +0000 | [diff] [blame] | 2367 | CXXDtorType Type = | 
|  | 2368 | CurGD.getCtorType() == Ctor_Complete ? Dtor_Complete : Dtor_Base; | 
|  | 2369 |  | 
|  | 2370 | EHStack.pushCleanup<CallDelegatingCtorDtor>(EHCleanup, | 
|  | 2371 | ClassDecl->getDestructor(), | 
|  | 2372 | ThisPtr, Type); | 
|  | 2373 | } | 
|  | 2374 | } | 
| Alexis Hunt | 61bc173 | 2011-05-01 07:04:31 +0000 | [diff] [blame] | 2375 |  | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 2376 | void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, | 
|  | 2377 | CXXDtorType Type, | 
| Anders Carlsson | f8a71f0 | 2010-05-02 23:29:11 +0000 | [diff] [blame] | 2378 | bool ForVirtualBase, | 
| Douglas Gregor | 6153500 | 2013-01-31 05:50:40 +0000 | [diff] [blame] | 2379 | bool Delegating, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2380 | Address This) { | 
| Reid Kleckner | 6fe771a | 2013-12-13 00:53:54 +0000 | [diff] [blame] | 2381 | CGM.getCXXABI().EmitDestructorCall(*this, DD, Type, ForVirtualBase, | 
|  | 2382 | Delegating, This); | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 2383 | } | 
|  | 2384 |  | 
| John McCall | 53cad2e | 2010-07-21 01:41:18 +0000 | [diff] [blame] | 2385 | namespace { | 
| David Blaikie | 7e70d68 | 2015-08-18 22:40:54 +0000 | [diff] [blame] | 2386 | struct CallLocalDtor final : EHScopeStack::Cleanup { | 
| John McCall | 53cad2e | 2010-07-21 01:41:18 +0000 | [diff] [blame] | 2387 | const CXXDestructorDecl *Dtor; | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2388 | Address Addr; | 
| John McCall | 53cad2e | 2010-07-21 01:41:18 +0000 | [diff] [blame] | 2389 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2390 | CallLocalDtor(const CXXDestructorDecl *D, Address Addr) | 
| John McCall | 53cad2e | 2010-07-21 01:41:18 +0000 | [diff] [blame] | 2391 | : Dtor(D), Addr(Addr) {} | 
|  | 2392 |  | 
| Craig Topper | 4f12f10 | 2014-03-12 06:41:41 +0000 | [diff] [blame] | 2393 | void Emit(CodeGenFunction &CGF, Flags flags) override { | 
| John McCall | 53cad2e | 2010-07-21 01:41:18 +0000 | [diff] [blame] | 2394 | CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, | 
| Douglas Gregor | 6153500 | 2013-01-31 05:50:40 +0000 | [diff] [blame] | 2395 | /*ForVirtualBase=*/false, | 
|  | 2396 | /*Delegating=*/false, Addr); | 
| John McCall | 53cad2e | 2010-07-21 01:41:18 +0000 | [diff] [blame] | 2397 | } | 
|  | 2398 | }; | 
| Eugene Zelenko | 0a4f3f4 | 2016-02-10 19:11:58 +0000 | [diff] [blame] | 2399 | } // end anonymous namespace | 
| John McCall | 53cad2e | 2010-07-21 01:41:18 +0000 | [diff] [blame] | 2400 |  | 
| John McCall | 8680f87 | 2010-07-21 06:29:51 +0000 | [diff] [blame] | 2401 | void CodeGenFunction::PushDestructorCleanup(const CXXDestructorDecl *D, | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2402 | Address Addr) { | 
| John McCall | cda666c | 2010-07-21 07:22:38 +0000 | [diff] [blame] | 2403 | EHStack.pushCleanup<CallLocalDtor>(NormalAndEHCleanup, D, Addr); | 
| John McCall | 8680f87 | 2010-07-21 06:29:51 +0000 | [diff] [blame] | 2404 | } | 
|  | 2405 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2406 | void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) { | 
| John McCall | bd30929 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 2407 | CXXRecordDecl *ClassDecl = T->getAsCXXRecordDecl(); | 
|  | 2408 | if (!ClassDecl) return; | 
|  | 2409 | if (ClassDecl->hasTrivialDestructor()) return; | 
|  | 2410 |  | 
|  | 2411 | const CXXDestructorDecl *D = ClassDecl->getDestructor(); | 
| John McCall | a85af56 | 2011-04-28 02:15:35 +0000 | [diff] [blame] | 2412 | assert(D && D->isUsed() && "destructor not marked as used!"); | 
| John McCall | 8680f87 | 2010-07-21 06:29:51 +0000 | [diff] [blame] | 2413 | PushDestructorCleanup(D, Addr); | 
| John McCall | bd30929 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 2414 | } | 
|  | 2415 |  | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2416 | void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) { | 
| Anders Carlsson | e87fae9 | 2010-03-28 19:40:00 +0000 | [diff] [blame] | 2417 | // Compute the address point. | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 2418 | llvm::Value *VTableAddressPoint = | 
|  | 2419 | CGM.getCXXABI().getVTableAddressPointInStructor( | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2420 | *this, Vptr.VTableClass, Vptr.Base, Vptr.NearestVBase); | 
|  | 2421 |  | 
| Timur Iskhodzhanov | 8b5987e | 2013-09-27 14:48:01 +0000 | [diff] [blame] | 2422 | if (!VTableAddressPoint) | 
|  | 2423 | return; | 
| Anders Carlsson | e87fae9 | 2010-03-28 19:40:00 +0000 | [diff] [blame] | 2424 |  | 
| Anders Carlsson | 6a0227d | 2010-04-20 16:22:16 +0000 | [diff] [blame] | 2425 | // Compute where to store the address point. | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 2426 | llvm::Value *VirtualOffset = nullptr; | 
| Ken Dyck | cfc332c | 2011-03-23 00:45:26 +0000 | [diff] [blame] | 2427 | CharUnits NonVirtualOffset = CharUnits::Zero(); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 2428 |  | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2429 | if (CGM.getCXXABI().isVirtualOffsetNeededForVTableField(*this, Vptr)) { | 
| Anders Carlsson | 91baecf | 2010-04-20 18:05:10 +0000 | [diff] [blame] | 2430 | // We need to use the virtual base offset offset because the virtual base | 
|  | 2431 | // might have a different offset in the most derived class. | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2432 |  | 
|  | 2433 | VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset( | 
|  | 2434 | *this, LoadCXXThisAddress(), Vptr.VTableClass, Vptr.NearestVBase); | 
|  | 2435 | NonVirtualOffset = Vptr.OffsetFromNearestVBase; | 
| Anders Carlsson | 91baecf | 2010-04-20 18:05:10 +0000 | [diff] [blame] | 2436 | } else { | 
| Anders Carlsson | c58fb55 | 2010-05-03 00:29:58 +0000 | [diff] [blame] | 2437 | // We can just use the base offset in the complete class. | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2438 | NonVirtualOffset = Vptr.Base.getBaseOffset(); | 
| Anders Carlsson | 91baecf | 2010-04-20 18:05:10 +0000 | [diff] [blame] | 2439 | } | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 2440 |  | 
| Anders Carlsson | c58fb55 | 2010-05-03 00:29:58 +0000 | [diff] [blame] | 2441 | // Apply the offsets. | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2442 | Address VTableField = LoadCXXThisAddress(); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 2443 |  | 
| Ken Dyck | cfc332c | 2011-03-23 00:45:26 +0000 | [diff] [blame] | 2444 | if (!NonVirtualOffset.isZero() || VirtualOffset) | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2445 | VTableField = ApplyNonVirtualAndVirtualOffset( | 
|  | 2446 | *this, VTableField, NonVirtualOffset, VirtualOffset, Vptr.VTableClass, | 
|  | 2447 | Vptr.NearestVBase); | 
| Anders Carlsson | 6a0227d | 2010-04-20 16:22:16 +0000 | [diff] [blame] | 2448 |  | 
| Reid Kleckner | 8d58513 | 2014-12-03 21:00:21 +0000 | [diff] [blame] | 2449 | // Finally, store the address point. Use the same LLVM types as the field to | 
|  | 2450 | // support optimization. | 
|  | 2451 | llvm::Type *VTablePtrTy = | 
|  | 2452 | llvm::FunctionType::get(CGM.Int32Ty, /*isVarArg=*/true) | 
|  | 2453 | ->getPointerTo() | 
|  | 2454 | ->getPointerTo(); | 
|  | 2455 | VTableField = Builder.CreateBitCast(VTableField, VTablePtrTy->getPointerTo()); | 
|  | 2456 | VTableAddressPoint = Builder.CreateBitCast(VTableAddressPoint, VTablePtrTy); | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2457 |  | 
| Kostya Serebryany | 141e46f | 2012-03-26 17:03:51 +0000 | [diff] [blame] | 2458 | llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint, VTableField); | 
| Ivan A. Kosarev | 4e50e70 | 2017-11-27 09:39:29 +0000 | [diff] [blame] | 2459 | TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(VTablePtrTy); | 
|  | 2460 | CGM.DecorateInstructionWithTBAA(Store, TBAAInfo); | 
| Piotr Padlewski | 4b1ac72 | 2015-09-15 21:46:55 +0000 | [diff] [blame] | 2461 | if (CGM.getCodeGenOpts().OptimizationLevel > 0 && | 
|  | 2462 | CGM.getCodeGenOpts().StrictVTablePointers) | 
|  | 2463 | CGM.DecorateInstructionWithInvariantGroup(Store, Vptr.VTableClass); | 
| Anders Carlsson | e87fae9 | 2010-03-28 19:40:00 +0000 | [diff] [blame] | 2464 | } | 
|  | 2465 |  | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2466 | CodeGenFunction::VPtrsVector | 
|  | 2467 | CodeGenFunction::getVTablePointers(const CXXRecordDecl *VTableClass) { | 
|  | 2468 | CodeGenFunction::VPtrsVector VPtrsResult; | 
|  | 2469 | VisitedVirtualBasesSetTy VBases; | 
|  | 2470 | getVTablePointers(BaseSubobject(VTableClass, CharUnits::Zero()), | 
|  | 2471 | /*NearestVBase=*/nullptr, | 
|  | 2472 | /*OffsetFromNearestVBase=*/CharUnits::Zero(), | 
|  | 2473 | /*BaseIsNonVirtualPrimaryBase=*/false, VTableClass, VBases, | 
|  | 2474 | VPtrsResult); | 
|  | 2475 | return VPtrsResult; | 
|  | 2476 | } | 
|  | 2477 |  | 
|  | 2478 | void CodeGenFunction::getVTablePointers(BaseSubobject Base, | 
|  | 2479 | const CXXRecordDecl *NearestVBase, | 
|  | 2480 | CharUnits OffsetFromNearestVBase, | 
|  | 2481 | bool BaseIsNonVirtualPrimaryBase, | 
|  | 2482 | const CXXRecordDecl *VTableClass, | 
|  | 2483 | VisitedVirtualBasesSetTy &VBases, | 
|  | 2484 | VPtrsVector &Vptrs) { | 
| Anders Carlsson | d589593 | 2010-03-28 21:07:49 +0000 | [diff] [blame] | 2485 | // If this base is a non-virtual primary base the address point has already | 
|  | 2486 | // been set. | 
|  | 2487 | if (!BaseIsNonVirtualPrimaryBase) { | 
|  | 2488 | // Initialize the vtable pointer for this base. | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2489 | VPtr Vptr = {Base, NearestVBase, OffsetFromNearestVBase, VTableClass}; | 
|  | 2490 | Vptrs.push_back(Vptr); | 
| Anders Carlsson | d589593 | 2010-03-28 21:07:49 +0000 | [diff] [blame] | 2491 | } | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 2492 |  | 
| Anders Carlsson | d589593 | 2010-03-28 21:07:49 +0000 | [diff] [blame] | 2493 | const CXXRecordDecl *RD = Base.getBase(); | 
|  | 2494 |  | 
|  | 2495 | // Traverse bases. | 
| Aaron Ballman | 574705e | 2014-03-13 15:41:46 +0000 | [diff] [blame] | 2496 | for (const auto &I : RD->bases()) { | 
| Anders Carlsson | d589593 | 2010-03-28 21:07:49 +0000 | [diff] [blame] | 2497 | CXXRecordDecl *BaseDecl | 
| Aaron Ballman | 574705e | 2014-03-13 15:41:46 +0000 | [diff] [blame] | 2498 | = cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl()); | 
| Anders Carlsson | d589593 | 2010-03-28 21:07:49 +0000 | [diff] [blame] | 2499 |  | 
|  | 2500 | // Ignore classes without a vtable. | 
|  | 2501 | if (!BaseDecl->isDynamicClass()) | 
|  | 2502 | continue; | 
|  | 2503 |  | 
| Ken Dyck | 3fb4c89 | 2011-03-23 01:04:18 +0000 | [diff] [blame] | 2504 | CharUnits BaseOffset; | 
|  | 2505 | CharUnits BaseOffsetFromNearestVBase; | 
| Anders Carlsson | 948d3f4 | 2010-03-29 01:16:41 +0000 | [diff] [blame] | 2506 | bool BaseDeclIsNonVirtualPrimaryBase; | 
| Anders Carlsson | d589593 | 2010-03-28 21:07:49 +0000 | [diff] [blame] | 2507 |  | 
| Aaron Ballman | 574705e | 2014-03-13 15:41:46 +0000 | [diff] [blame] | 2508 | if (I.isVirtual()) { | 
| Anders Carlsson | d589593 | 2010-03-28 21:07:49 +0000 | [diff] [blame] | 2509 | // Check if we've visited this virtual base before. | 
| David Blaikie | 82e95a3 | 2014-11-19 07:49:47 +0000 | [diff] [blame] | 2510 | if (!VBases.insert(BaseDecl).second) | 
| Anders Carlsson | d589593 | 2010-03-28 21:07:49 +0000 | [diff] [blame] | 2511 | continue; | 
|  | 2512 |  | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 2513 | const ASTRecordLayout &Layout = | 
| Anders Carlsson | d589593 | 2010-03-28 21:07:49 +0000 | [diff] [blame] | 2514 | getContext().getASTRecordLayout(VTableClass); | 
|  | 2515 |  | 
| Ken Dyck | 3fb4c89 | 2011-03-23 01:04:18 +0000 | [diff] [blame] | 2516 | BaseOffset = Layout.getVBaseClassOffset(BaseDecl); | 
|  | 2517 | BaseOffsetFromNearestVBase = CharUnits::Zero(); | 
| Anders Carlsson | 948d3f4 | 2010-03-29 01:16:41 +0000 | [diff] [blame] | 2518 | BaseDeclIsNonVirtualPrimaryBase = false; | 
| Anders Carlsson | d589593 | 2010-03-28 21:07:49 +0000 | [diff] [blame] | 2519 | } else { | 
|  | 2520 | const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); | 
|  | 2521 |  | 
| Ken Dyck | 16ffcac | 2011-03-24 01:21:01 +0000 | [diff] [blame] | 2522 | BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl); | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 2523 | BaseOffsetFromNearestVBase = | 
| Ken Dyck | 3fb4c89 | 2011-03-23 01:04:18 +0000 | [diff] [blame] | 2524 | OffsetFromNearestVBase + Layout.getBaseClassOffset(BaseDecl); | 
| Anders Carlsson | 948d3f4 | 2010-03-29 01:16:41 +0000 | [diff] [blame] | 2525 | BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl; | 
| Anders Carlsson | d589593 | 2010-03-28 21:07:49 +0000 | [diff] [blame] | 2526 | } | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 2527 |  | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2528 | getVTablePointers( | 
|  | 2529 | BaseSubobject(BaseDecl, BaseOffset), | 
|  | 2530 | I.isVirtual() ? BaseDecl : NearestVBase, BaseOffsetFromNearestVBase, | 
|  | 2531 | BaseDeclIsNonVirtualPrimaryBase, VTableClass, VBases, Vptrs); | 
| Anders Carlsson | d589593 | 2010-03-28 21:07:49 +0000 | [diff] [blame] | 2532 | } | 
|  | 2533 | } | 
|  | 2534 |  | 
|  | 2535 | void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) { | 
|  | 2536 | // Ignore classes without a vtable. | 
| Anders Carlsson | 1f9348c | 2010-03-26 04:39:42 +0000 | [diff] [blame] | 2537 | if (!RD->isDynamicClass()) | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 2538 | return; | 
|  | 2539 |  | 
| Anders Carlsson | d589593 | 2010-03-28 21:07:49 +0000 | [diff] [blame] | 2540 | // Initialize the vtable pointers for this class and all of its bases. | 
| Piotr Padlewski | d679d7e | 2015-09-15 00:37:06 +0000 | [diff] [blame] | 2541 | if (CGM.getCXXABI().doStructorsInitializeVPtrs(RD)) | 
|  | 2542 | for (const VPtr &Vptr : getVTablePointers(RD)) | 
|  | 2543 | InitializeVTablePointer(Vptr); | 
| Timur Iskhodzhanov | b648732 | 2013-10-09 18:16:58 +0000 | [diff] [blame] | 2544 |  | 
|  | 2545 | if (RD->getNumVBases()) | 
|  | 2546 | CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, RD); | 
| Anders Carlsson | 27da15b | 2010-01-01 20:29:01 +0000 | [diff] [blame] | 2547 | } | 
| Dan Gohman | 8fc50c2 | 2010-10-26 18:44:08 +0000 | [diff] [blame] | 2548 |  | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2549 | llvm::Value *CodeGenFunction::GetVTablePtr(Address This, | 
| Piotr Padlewski | 4b1ac72 | 2015-09-15 21:46:55 +0000 | [diff] [blame] | 2550 | llvm::Type *VTableTy, | 
|  | 2551 | const CXXRecordDecl *RD) { | 
|  | 2552 | Address VTablePtrSrc = Builder.CreateElementBitCast(This, VTableTy); | 
| Kostya Serebryany | 141e46f | 2012-03-26 17:03:51 +0000 | [diff] [blame] | 2553 | llvm::Instruction *VTable = Builder.CreateLoad(VTablePtrSrc, "vtable"); | 
| Ivan A. Kosarev | 4e50e70 | 2017-11-27 09:39:29 +0000 | [diff] [blame] | 2554 | TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(VTableTy); | 
|  | 2555 | CGM.DecorateInstructionWithTBAA(VTable, TBAAInfo); | 
| Piotr Padlewski | 4b1ac72 | 2015-09-15 21:46:55 +0000 | [diff] [blame] | 2556 |  | 
|  | 2557 | if (CGM.getCodeGenOpts().OptimizationLevel > 0 && | 
|  | 2558 | CGM.getCodeGenOpts().StrictVTablePointers) | 
|  | 2559 | CGM.DecorateInstructionWithInvariantGroup(VTable, RD); | 
|  | 2560 |  | 
| Kostya Serebryany | 141e46f | 2012-03-26 17:03:51 +0000 | [diff] [blame] | 2561 | return VTable; | 
| Dan Gohman | 8fc50c2 | 2010-10-26 18:44:08 +0000 | [diff] [blame] | 2562 | } | 
| Anders Carlsson | c36783e | 2011-05-08 20:32:23 +0000 | [diff] [blame] | 2563 |  | 
| Peter Collingbourne | d2926c9 | 2015-03-14 02:42:25 +0000 | [diff] [blame] | 2564 | // If a class has a single non-virtual base and does not introduce or override | 
|  | 2565 | // virtual member functions or fields, it will have the same layout as its base. | 
|  | 2566 | // This function returns the least derived such class. | 
|  | 2567 | // | 
|  | 2568 | // Casting an instance of a base class to such a derived class is technically | 
|  | 2569 | // undefined behavior, but it is a relatively common hack for introducing member | 
|  | 2570 | // functions on class instances with specific properties (e.g. llvm::Operator) | 
|  | 2571 | // that works under most compilers and should not have security implications, so | 
|  | 2572 | // we allow it by default. It can be disabled with -fsanitize=cfi-cast-strict. | 
|  | 2573 | static const CXXRecordDecl * | 
|  | 2574 | LeastDerivedClassWithSameLayout(const CXXRecordDecl *RD) { | 
|  | 2575 | if (!RD->field_empty()) | 
|  | 2576 | return RD; | 
|  | 2577 |  | 
|  | 2578 | if (RD->getNumVBases() != 0) | 
|  | 2579 | return RD; | 
|  | 2580 |  | 
|  | 2581 | if (RD->getNumBases() != 1) | 
|  | 2582 | return RD; | 
|  | 2583 |  | 
|  | 2584 | for (const CXXMethodDecl *MD : RD->methods()) { | 
|  | 2585 | if (MD->isVirtual()) { | 
|  | 2586 | // Virtual member functions are only ok if they are implicit destructors | 
|  | 2587 | // because the implicit destructor will have the same semantics as the | 
|  | 2588 | // base class's destructor if no fields are added. | 
|  | 2589 | if (isa<CXXDestructorDecl>(MD) && MD->isImplicit()) | 
|  | 2590 | continue; | 
|  | 2591 | return RD; | 
|  | 2592 | } | 
|  | 2593 | } | 
|  | 2594 |  | 
|  | 2595 | return LeastDerivedClassWithSameLayout( | 
|  | 2596 | RD->bases_begin()->getType()->getAsCXXRecordDecl()); | 
|  | 2597 | } | 
|  | 2598 |  | 
| Peter Collingbourne | 8dd14da | 2016-06-24 21:21:46 +0000 | [diff] [blame] | 2599 | void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD, | 
|  | 2600 | llvm::Value *VTable, | 
|  | 2601 | SourceLocation Loc) { | 
| Peter Collingbourne | 396943a | 2017-07-31 22:35:33 +0000 | [diff] [blame] | 2602 | if (SanOpts.has(SanitizerKind::CFIVCall)) | 
|  | 2603 | EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc); | 
|  | 2604 | else if (CGM.getCodeGenOpts().WholeProgramVTables && | 
|  | 2605 | CGM.HasHiddenLTOVisibility(RD)) { | 
| Peter Collingbourne | fb532b9 | 2016-02-24 20:46:36 +0000 | [diff] [blame] | 2606 | llvm::Metadata *MD = | 
|  | 2607 | CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); | 
| Peter Collingbourne | 8dd14da | 2016-06-24 21:21:46 +0000 | [diff] [blame] | 2608 | llvm::Value *TypeId = | 
| Peter Collingbourne | fb532b9 | 2016-02-24 20:46:36 +0000 | [diff] [blame] | 2609 | llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD); | 
|  | 2610 |  | 
|  | 2611 | llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy); | 
| Peter Collingbourne | 8dd14da | 2016-06-24 21:21:46 +0000 | [diff] [blame] | 2612 | llvm::Value *TypeTest = | 
|  | 2613 | Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test), | 
|  | 2614 | {CastedVTable, TypeId}); | 
|  | 2615 | Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest); | 
| Peter Collingbourne | fb532b9 | 2016-02-24 20:46:36 +0000 | [diff] [blame] | 2616 | } | 
| Peter Collingbourne | fb532b9 | 2016-02-24 20:46:36 +0000 | [diff] [blame] | 2617 | } | 
|  | 2618 |  | 
|  | 2619 | void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXRecordDecl *RD, | 
| Peter Collingbourne | 6708c4a | 2015-06-19 01:51:54 +0000 | [diff] [blame] | 2620 | llvm::Value *VTable, | 
|  | 2621 | CFITypeCheckKind TCK, | 
|  | 2622 | SourceLocation Loc) { | 
| Peter Collingbourne | 1a7488a | 2015-04-02 00:23:30 +0000 | [diff] [blame] | 2623 | if (!SanOpts.has(SanitizerKind::CFICastStrict)) | 
| Peter Collingbourne | fb532b9 | 2016-02-24 20:46:36 +0000 | [diff] [blame] | 2624 | RD = LeastDerivedClassWithSameLayout(RD); | 
| Peter Collingbourne | 1a7488a | 2015-04-02 00:23:30 +0000 | [diff] [blame] | 2625 |  | 
| Peter Collingbourne | fb532b9 | 2016-02-24 20:46:36 +0000 | [diff] [blame] | 2626 | EmitVTablePtrCheck(RD, VTable, TCK, Loc); | 
| Peter Collingbourne | 1a7488a | 2015-04-02 00:23:30 +0000 | [diff] [blame] | 2627 | } | 
|  | 2628 |  | 
| Peter Collingbourne | d2926c9 | 2015-03-14 02:42:25 +0000 | [diff] [blame] | 2629 | void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, | 
|  | 2630 | llvm::Value *Derived, | 
| Peter Collingbourne | 6708c4a | 2015-06-19 01:51:54 +0000 | [diff] [blame] | 2631 | bool MayBeNull, | 
|  | 2632 | CFITypeCheckKind TCK, | 
|  | 2633 | SourceLocation Loc) { | 
| Peter Collingbourne | d2926c9 | 2015-03-14 02:42:25 +0000 | [diff] [blame] | 2634 | if (!getLangOpts().CPlusPlus) | 
|  | 2635 | return; | 
|  | 2636 |  | 
|  | 2637 | auto *ClassTy = T->getAs<RecordType>(); | 
|  | 2638 | if (!ClassTy) | 
|  | 2639 | return; | 
|  | 2640 |  | 
|  | 2641 | const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassTy->getDecl()); | 
|  | 2642 |  | 
|  | 2643 | if (!ClassDecl->isCompleteDefinition() || !ClassDecl->isDynamicClass()) | 
|  | 2644 | return; | 
|  | 2645 |  | 
| Peter Collingbourne | d2926c9 | 2015-03-14 02:42:25 +0000 | [diff] [blame] | 2646 | if (!SanOpts.has(SanitizerKind::CFICastStrict)) | 
|  | 2647 | ClassDecl = LeastDerivedClassWithSameLayout(ClassDecl); | 
|  | 2648 |  | 
| Hans Wennborg | dcfba33 | 2015-10-06 23:40:43 +0000 | [diff] [blame] | 2649 | llvm::BasicBlock *ContBlock = nullptr; | 
| Peter Collingbourne | d2926c9 | 2015-03-14 02:42:25 +0000 | [diff] [blame] | 2650 |  | 
|  | 2651 | if (MayBeNull) { | 
|  | 2652 | llvm::Value *DerivedNotNull = | 
|  | 2653 | Builder.CreateIsNotNull(Derived, "cast.nonnull"); | 
|  | 2654 |  | 
|  | 2655 | llvm::BasicBlock *CheckBlock = createBasicBlock("cast.check"); | 
|  | 2656 | ContBlock = createBasicBlock("cast.cont"); | 
|  | 2657 |  | 
|  | 2658 | Builder.CreateCondBr(DerivedNotNull, CheckBlock, ContBlock); | 
|  | 2659 |  | 
|  | 2660 | EmitBlock(CheckBlock); | 
|  | 2661 | } | 
|  | 2662 |  | 
| Peter Collingbourne | 6010880 | 2017-12-13 21:53:04 +0000 | [diff] [blame] | 2663 | llvm::Value *VTable; | 
|  | 2664 | std::tie(VTable, ClassDecl) = CGM.getCXXABI().LoadVTablePtr( | 
|  | 2665 | *this, Address(Derived, getPointerAlign()), ClassDecl); | 
| Piotr Padlewski | 4b1ac72 | 2015-09-15 21:46:55 +0000 | [diff] [blame] | 2666 |  | 
| Peter Collingbourne | 6708c4a | 2015-06-19 01:51:54 +0000 | [diff] [blame] | 2667 | EmitVTablePtrCheck(ClassDecl, VTable, TCK, Loc); | 
| Peter Collingbourne | d2926c9 | 2015-03-14 02:42:25 +0000 | [diff] [blame] | 2668 |  | 
|  | 2669 | if (MayBeNull) { | 
|  | 2670 | Builder.CreateBr(ContBlock); | 
|  | 2671 | EmitBlock(ContBlock); | 
|  | 2672 | } | 
|  | 2673 | } | 
|  | 2674 |  | 
|  | 2675 | void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD, | 
| Peter Collingbourne | 6708c4a | 2015-06-19 01:51:54 +0000 | [diff] [blame] | 2676 | llvm::Value *VTable, | 
|  | 2677 | CFITypeCheckKind TCK, | 
|  | 2678 | SourceLocation Loc) { | 
| Peter Collingbourne | 3afb266 | 2016-04-28 17:09:37 +0000 | [diff] [blame] | 2679 | if (!CGM.getCodeGenOpts().SanitizeCfiCrossDso && | 
|  | 2680 | !CGM.HasHiddenLTOVisibility(RD)) | 
|  | 2681 | return; | 
|  | 2682 |  | 
| Vlad Tsyrklevich | 2eccdab | 2017-09-25 22:11:12 +0000 | [diff] [blame] | 2683 | SanitizerMask M; | 
| Peter Collingbourne | dc13453 | 2016-01-16 00:31:22 +0000 | [diff] [blame] | 2684 | llvm::SanitizerStatKind SSK; | 
|  | 2685 | switch (TCK) { | 
|  | 2686 | case CFITCK_VCall: | 
| Vlad Tsyrklevich | 2eccdab | 2017-09-25 22:11:12 +0000 | [diff] [blame] | 2687 | M = SanitizerKind::CFIVCall; | 
| Peter Collingbourne | dc13453 | 2016-01-16 00:31:22 +0000 | [diff] [blame] | 2688 | SSK = llvm::SanStat_CFI_VCall; | 
|  | 2689 | break; | 
|  | 2690 | case CFITCK_NVCall: | 
| Vlad Tsyrklevich | 2eccdab | 2017-09-25 22:11:12 +0000 | [diff] [blame] | 2691 | M = SanitizerKind::CFINVCall; | 
| Peter Collingbourne | dc13453 | 2016-01-16 00:31:22 +0000 | [diff] [blame] | 2692 | SSK = llvm::SanStat_CFI_NVCall; | 
|  | 2693 | break; | 
|  | 2694 | case CFITCK_DerivedCast: | 
| Vlad Tsyrklevich | 2eccdab | 2017-09-25 22:11:12 +0000 | [diff] [blame] | 2695 | M = SanitizerKind::CFIDerivedCast; | 
| Peter Collingbourne | dc13453 | 2016-01-16 00:31:22 +0000 | [diff] [blame] | 2696 | SSK = llvm::SanStat_CFI_DerivedCast; | 
|  | 2697 | break; | 
|  | 2698 | case CFITCK_UnrelatedCast: | 
| Vlad Tsyrklevich | 2eccdab | 2017-09-25 22:11:12 +0000 | [diff] [blame] | 2699 | M = SanitizerKind::CFIUnrelatedCast; | 
| Peter Collingbourne | dc13453 | 2016-01-16 00:31:22 +0000 | [diff] [blame] | 2700 | SSK = llvm::SanStat_CFI_UnrelatedCast; | 
|  | 2701 | break; | 
| Evgeniy Stepanov | 3fd61df | 2016-01-25 23:34:52 +0000 | [diff] [blame] | 2702 | case CFITCK_ICall: | 
| Peter Collingbourne | e44acad | 2018-06-26 02:15:47 +0000 | [diff] [blame] | 2703 | case CFITCK_NVMFCall: | 
|  | 2704 | case CFITCK_VMFCall: | 
|  | 2705 | llvm_unreachable("unexpected sanitizer kind"); | 
| Peter Collingbourne | dc13453 | 2016-01-16 00:31:22 +0000 | [diff] [blame] | 2706 | } | 
| Vlad Tsyrklevich | 2eccdab | 2017-09-25 22:11:12 +0000 | [diff] [blame] | 2707 |  | 
|  | 2708 | std::string TypeName = RD->getQualifiedNameAsString(); | 
|  | 2709 | if (getContext().getSanitizerBlacklist().isBlacklistedType(M, TypeName)) | 
|  | 2710 | return; | 
|  | 2711 |  | 
|  | 2712 | SanitizerScope SanScope(this); | 
| Peter Collingbourne | dc13453 | 2016-01-16 00:31:22 +0000 | [diff] [blame] | 2713 | EmitSanitizerStatReport(SSK); | 
| Peter Collingbourne | 6708c4a | 2015-06-19 01:51:54 +0000 | [diff] [blame] | 2714 |  | 
| Evgeniy Stepanov | fd6f92d | 2015-12-15 23:00:20 +0000 | [diff] [blame] | 2715 | llvm::Metadata *MD = | 
|  | 2716 | CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); | 
| Peter Collingbourne | 8dd14da | 2016-06-24 21:21:46 +0000 | [diff] [blame] | 2717 | llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD); | 
| Peter Collingbourne | a4ccff3 | 2015-02-20 20:30:56 +0000 | [diff] [blame] | 2718 |  | 
| Peter Collingbourne | 6708c4a | 2015-06-19 01:51:54 +0000 | [diff] [blame] | 2719 | llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy); | 
| Peter Collingbourne | 8dd14da | 2016-06-24 21:21:46 +0000 | [diff] [blame] | 2720 | llvm::Value *TypeTest = Builder.CreateCall( | 
|  | 2721 | CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedVTable, TypeId}); | 
| Peter Collingbourne | a4ccff3 | 2015-02-20 20:30:56 +0000 | [diff] [blame] | 2722 |  | 
| Peter Collingbourne | 6708c4a | 2015-06-19 01:51:54 +0000 | [diff] [blame] | 2723 | llvm::Constant *StaticData[] = { | 
| Evgeniy Stepanov | 3fd61df | 2016-01-25 23:34:52 +0000 | [diff] [blame] | 2724 | llvm::ConstantInt::get(Int8Ty, TCK), | 
| Evgeniy Stepanov | fd6f92d | 2015-12-15 23:00:20 +0000 | [diff] [blame] | 2725 | EmitCheckSourceLocation(Loc), | 
|  | 2726 | EmitCheckTypeDescriptor(QualType(RD->getTypeForDecl(), 0)), | 
| Peter Collingbourne | 6708c4a | 2015-06-19 01:51:54 +0000 | [diff] [blame] | 2727 | }; | 
| Evgeniy Stepanov | 3fd61df | 2016-01-25 23:34:52 +0000 | [diff] [blame] | 2728 |  | 
| Peter Collingbourne | 8dd14da | 2016-06-24 21:21:46 +0000 | [diff] [blame] | 2729 | auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD); | 
|  | 2730 | if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) { | 
|  | 2731 | EmitCfiSlowPathCheck(M, TypeTest, CrossDsoTypeId, CastedVTable, StaticData); | 
| Evgeniy Stepanov | f31ea30 | 2016-02-03 22:18:55 +0000 | [diff] [blame] | 2732 | return; | 
| Evgeniy Stepanov | 3fd61df | 2016-01-25 23:34:52 +0000 | [diff] [blame] | 2733 | } | 
| Evgeniy Stepanov | f31ea30 | 2016-02-03 22:18:55 +0000 | [diff] [blame] | 2734 |  | 
|  | 2735 | if (CGM.getCodeGenOpts().SanitizeTrap.has(M)) { | 
| Peter Collingbourne | 8dd14da | 2016-06-24 21:21:46 +0000 | [diff] [blame] | 2736 | EmitTrapCheck(TypeTest); | 
| Evgeniy Stepanov | f31ea30 | 2016-02-03 22:18:55 +0000 | [diff] [blame] | 2737 | return; | 
|  | 2738 | } | 
|  | 2739 |  | 
|  | 2740 | llvm::Value *AllVtables = llvm::MetadataAsValue::get( | 
|  | 2741 | CGM.getLLVMContext(), | 
|  | 2742 | llvm::MDString::get(CGM.getLLVMContext(), "all-vtables")); | 
| Peter Collingbourne | 8dd14da | 2016-06-24 21:21:46 +0000 | [diff] [blame] | 2743 | llvm::Value *ValidVtable = Builder.CreateCall( | 
|  | 2744 | CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedVTable, AllVtables}); | 
| Filipe Cabecinhas | 322ecd9 | 2016-12-12 16:18:40 +0000 | [diff] [blame] | 2745 | EmitCheck(std::make_pair(TypeTest, M), SanitizerHandler::CFICheckFail, | 
|  | 2746 | StaticData, {CastedVTable, ValidVtable}); | 
| Peter Collingbourne | a4ccff3 | 2015-02-20 20:30:56 +0000 | [diff] [blame] | 2747 | } | 
| Anders Carlsson | c36783e | 2011-05-08 20:32:23 +0000 | [diff] [blame] | 2748 |  | 
| Peter Collingbourne | 0ca0363 | 2016-06-25 00:24:06 +0000 | [diff] [blame] | 2749 | bool CodeGenFunction::ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD) { | 
|  | 2750 | if (!CGM.getCodeGenOpts().WholeProgramVTables || | 
|  | 2751 | !SanOpts.has(SanitizerKind::CFIVCall) || | 
|  | 2752 | !CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIVCall) || | 
|  | 2753 | !CGM.HasHiddenLTOVisibility(RD)) | 
|  | 2754 | return false; | 
|  | 2755 |  | 
|  | 2756 | std::string TypeName = RD->getQualifiedNameAsString(); | 
| Vlad Tsyrklevich | 2eccdab | 2017-09-25 22:11:12 +0000 | [diff] [blame] | 2757 | return !getContext().getSanitizerBlacklist().isBlacklistedType( | 
|  | 2758 | SanitizerKind::CFIVCall, TypeName); | 
| Peter Collingbourne | 0ca0363 | 2016-06-25 00:24:06 +0000 | [diff] [blame] | 2759 | } | 
|  | 2760 |  | 
|  | 2761 | llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad( | 
|  | 2762 | const CXXRecordDecl *RD, llvm::Value *VTable, uint64_t VTableByteOffset) { | 
|  | 2763 | SanitizerScope SanScope(this); | 
|  | 2764 |  | 
|  | 2765 | EmitSanitizerStatReport(llvm::SanStat_CFI_VCall); | 
|  | 2766 |  | 
|  | 2767 | llvm::Metadata *MD = | 
|  | 2768 | CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); | 
|  | 2769 | llvm::Value *TypeId = llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD); | 
|  | 2770 |  | 
|  | 2771 | llvm::Value *CastedVTable = Builder.CreateBitCast(VTable, Int8PtrTy); | 
|  | 2772 | llvm::Value *CheckedLoad = Builder.CreateCall( | 
|  | 2773 | CGM.getIntrinsic(llvm::Intrinsic::type_checked_load), | 
|  | 2774 | {CastedVTable, llvm::ConstantInt::get(Int32Ty, VTableByteOffset), | 
|  | 2775 | TypeId}); | 
|  | 2776 | llvm::Value *CheckResult = Builder.CreateExtractValue(CheckedLoad, 1); | 
|  | 2777 |  | 
|  | 2778 | EmitCheck(std::make_pair(CheckResult, SanitizerKind::CFIVCall), | 
| Filipe Cabecinhas | 322ecd9 | 2016-12-12 16:18:40 +0000 | [diff] [blame] | 2779 | SanitizerHandler::CFICheckFail, nullptr, nullptr); | 
| Peter Collingbourne | 0ca0363 | 2016-06-25 00:24:06 +0000 | [diff] [blame] | 2780 |  | 
|  | 2781 | return Builder.CreateBitCast( | 
|  | 2782 | Builder.CreateExtractValue(CheckedLoad, 0), | 
|  | 2783 | cast<llvm::PointerType>(VTable->getType())->getElementType()); | 
|  | 2784 | } | 
|  | 2785 |  | 
| Faisal Vali | 571df12 | 2013-09-29 08:45:24 +0000 | [diff] [blame] | 2786 | void CodeGenFunction::EmitForwardingCallToLambda( | 
|  | 2787 | const CXXMethodDecl *callOperator, | 
|  | 2788 | CallArgList &callArgs) { | 
| Eli Friedman | 5b44688 | 2012-02-16 03:47:28 +0000 | [diff] [blame] | 2789 | // Get the address of the call operator. | 
| John McCall | 8dda7b2 | 2012-07-07 06:41:13 +0000 | [diff] [blame] | 2790 | const CGFunctionInfo &calleeFnInfo = | 
|  | 2791 | CGM.getTypes().arrangeCXXMethodDeclaration(callOperator); | 
| John McCall | b92ab1a | 2016-10-26 23:46:34 +0000 | [diff] [blame] | 2792 | llvm::Constant *calleePtr = | 
| John McCall | 8dda7b2 | 2012-07-07 06:41:13 +0000 | [diff] [blame] | 2793 | CGM.GetAddrOfFunction(GlobalDecl(callOperator), | 
|  | 2794 | CGM.getTypes().GetFunctionType(calleeFnInfo)); | 
| Eli Friedman | 5b44688 | 2012-02-16 03:47:28 +0000 | [diff] [blame] | 2795 |  | 
| John McCall | 8dda7b2 | 2012-07-07 06:41:13 +0000 | [diff] [blame] | 2796 | // Prepare the return slot. | 
|  | 2797 | const FunctionProtoType *FPT = | 
|  | 2798 | callOperator->getType()->castAs<FunctionProtoType>(); | 
| Alp Toker | 314cc81 | 2014-01-25 16:55:45 +0000 | [diff] [blame] | 2799 | QualType resultType = FPT->getReturnType(); | 
| John McCall | 8dda7b2 | 2012-07-07 06:41:13 +0000 | [diff] [blame] | 2800 | ReturnValueSlot returnSlot; | 
|  | 2801 | if (!resultType->isVoidType() && | 
|  | 2802 | calleeFnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect && | 
| John McCall | 47fb950 | 2013-03-07 21:37:08 +0000 | [diff] [blame] | 2803 | !hasScalarEvaluationKind(calleeFnInfo.getReturnType())) | 
| John McCall | 8dda7b2 | 2012-07-07 06:41:13 +0000 | [diff] [blame] | 2804 | returnSlot = ReturnValueSlot(ReturnValue, resultType.isVolatileQualified()); | 
|  | 2805 |  | 
|  | 2806 | // We don't need to separately arrange the call arguments because | 
|  | 2807 | // the call can't be variadic anyway --- it's impossible to forward | 
|  | 2808 | // variadic arguments. | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 2809 |  | 
| Eli Friedman | 5b44688 | 2012-02-16 03:47:28 +0000 | [diff] [blame] | 2810 | // Now emit our call. | 
| John McCall | b92ab1a | 2016-10-26 23:46:34 +0000 | [diff] [blame] | 2811 | auto callee = CGCallee::forDirect(calleePtr, callOperator); | 
|  | 2812 | RValue RV = EmitCall(calleeFnInfo, callee, returnSlot, callArgs); | 
| Eli Friedman | 5b44688 | 2012-02-16 03:47:28 +0000 | [diff] [blame] | 2813 |  | 
| John McCall | 8dda7b2 | 2012-07-07 06:41:13 +0000 | [diff] [blame] | 2814 | // If necessary, copy the returned value into the slot. | 
| John McCall | 9508845 | 2017-12-14 18:21:14 +0000 | [diff] [blame] | 2815 | if (!resultType->isVoidType() && returnSlot.isNull()) { | 
|  | 2816 | if (getLangOpts().ObjCAutoRefCount && resultType->isObjCRetainableType()) { | 
|  | 2817 | RV = RValue::get(EmitARCRetainAutoreleasedReturnValue(RV.getScalarVal())); | 
|  | 2818 | } | 
| John McCall | 8dda7b2 | 2012-07-07 06:41:13 +0000 | [diff] [blame] | 2819 | EmitReturnOfRValue(RV, resultType); | 
| John McCall | 9508845 | 2017-12-14 18:21:14 +0000 | [diff] [blame] | 2820 | } else | 
| Eli Friedman | f5f4d2f | 2012-12-13 23:37:17 +0000 | [diff] [blame] | 2821 | EmitBranchThroughCleanup(ReturnBlock); | 
| Eli Friedman | 5b44688 | 2012-02-16 03:47:28 +0000 | [diff] [blame] | 2822 | } | 
|  | 2823 |  | 
| Eli Friedman | 2495ab0 | 2012-02-25 02:48:22 +0000 | [diff] [blame] | 2824 | void CodeGenFunction::EmitLambdaBlockInvokeBody() { | 
|  | 2825 | const BlockDecl *BD = BlockInfo->getBlockDecl(); | 
|  | 2826 | const VarDecl *variable = BD->capture_begin()->getVariable(); | 
|  | 2827 | const CXXRecordDecl *Lambda = variable->getType()->getAsCXXRecordDecl(); | 
| Reid Kleckner | 2d3c421 | 2017-08-04 22:38:06 +0000 | [diff] [blame] | 2828 | const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator(); | 
|  | 2829 |  | 
|  | 2830 | if (CallOp->isVariadic()) { | 
|  | 2831 | // FIXME: Making this work correctly is nasty because it requires either | 
|  | 2832 | // cloning the body of the call operator or making the call operator | 
|  | 2833 | // forward. | 
|  | 2834 | CGM.ErrorUnsupported(CurCodeDecl, "lambda conversion to variadic function"); | 
|  | 2835 | return; | 
|  | 2836 | } | 
| Eli Friedman | 2495ab0 | 2012-02-25 02:48:22 +0000 | [diff] [blame] | 2837 |  | 
|  | 2838 | // Start building arguments for forwarding call | 
|  | 2839 | CallArgList CallArgs; | 
|  | 2840 |  | 
|  | 2841 | QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda)); | 
| Akira Hatanaka | 9bd2452 | 2018-09-09 05:22:49 +0000 | [diff] [blame] | 2842 | Address ThisPtr = GetAddrOfBlockDecl(variable, false); | 
| John McCall | 7f416cc | 2015-09-08 08:05:57 +0000 | [diff] [blame] | 2843 | CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); | 
| Eli Friedman | 2495ab0 | 2012-02-25 02:48:22 +0000 | [diff] [blame] | 2844 |  | 
|  | 2845 | // Add the rest of the parameters. | 
| David Majnemer | 59f7792 | 2016-06-24 04:05:48 +0000 | [diff] [blame] | 2846 | for (auto param : BD->parameters()) | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 2847 | EmitDelegateCallArg(CallArgs, param, param->getBeginLoc()); | 
| Aaron Ballman | b2b8b1d | 2014-03-07 16:09:59 +0000 | [diff] [blame] | 2848 |  | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 2849 | assert(!Lambda->isGenericLambda() && | 
| Faisal Vali | 571df12 | 2013-09-29 08:45:24 +0000 | [diff] [blame] | 2850 | "generic lambda interconversion to block not implemented"); | 
| Reid Kleckner | 2d3c421 | 2017-08-04 22:38:06 +0000 | [diff] [blame] | 2851 | EmitForwardingCallToLambda(CallOp, CallArgs); | 
| Eli Friedman | 2495ab0 | 2012-02-25 02:48:22 +0000 | [diff] [blame] | 2852 | } | 
|  | 2853 |  | 
|  | 2854 | void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD) { | 
|  | 2855 | const CXXRecordDecl *Lambda = MD->getParent(); | 
|  | 2856 |  | 
|  | 2857 | // Start building arguments for forwarding call | 
|  | 2858 | CallArgList CallArgs; | 
|  | 2859 |  | 
|  | 2860 | QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda)); | 
|  | 2861 | llvm::Value *ThisPtr = llvm::UndefValue::get(getTypes().ConvertType(ThisType)); | 
|  | 2862 | CallArgs.add(RValue::get(ThisPtr), ThisType); | 
|  | 2863 |  | 
|  | 2864 | // Add the rest of the parameters. | 
| David Majnemer | 59f7792 | 2016-06-24 04:05:48 +0000 | [diff] [blame] | 2865 | for (auto Param : MD->parameters()) | 
| Stephen Kelly | f2ceec4 | 2018-08-09 21:08:08 +0000 | [diff] [blame] | 2866 | EmitDelegateCallArg(CallArgs, Param, Param->getBeginLoc()); | 
| Aaron Ballman | f6bf62e | 2014-03-07 15:12:56 +0000 | [diff] [blame] | 2867 |  | 
| Faisal Vali | 571df12 | 2013-09-29 08:45:24 +0000 | [diff] [blame] | 2868 | const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator(); | 
|  | 2869 | // For a generic lambda, find the corresponding call operator specialization | 
|  | 2870 | // to which the call to the static-invoker shall be forwarded. | 
|  | 2871 | if (Lambda->isGenericLambda()) { | 
|  | 2872 | assert(MD->isFunctionTemplateSpecialization()); | 
|  | 2873 | const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs(); | 
|  | 2874 | FunctionTemplateDecl *CallOpTemplate = CallOp->getDescribedFunctionTemplate(); | 
| Craig Topper | 8a13c41 | 2014-05-21 05:09:00 +0000 | [diff] [blame] | 2875 | void *InsertPos = nullptr; | 
| Justin Bogner | 1cd11f1 | 2015-05-20 15:53:59 +0000 | [diff] [blame] | 2876 | FunctionDecl *CorrespondingCallOpSpecialization = | 
| Craig Topper | 7e0daca | 2014-06-26 04:58:53 +0000 | [diff] [blame] | 2877 | CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos); | 
| Faisal Vali | 571df12 | 2013-09-29 08:45:24 +0000 | [diff] [blame] | 2878 | assert(CorrespondingCallOpSpecialization); | 
|  | 2879 | CallOp = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization); | 
|  | 2880 | } | 
|  | 2881 | EmitForwardingCallToLambda(CallOp, CallArgs); | 
| Eli Friedman | 2495ab0 | 2012-02-25 02:48:22 +0000 | [diff] [blame] | 2882 | } | 
|  | 2883 |  | 
| Reid Kleckner | 2d3c421 | 2017-08-04 22:38:06 +0000 | [diff] [blame] | 2884 | void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) { | 
| Douglas Gregor | 355efbb | 2012-02-17 03:02:34 +0000 | [diff] [blame] | 2885 | if (MD->isVariadic()) { | 
| Eli Friedman | 5b44688 | 2012-02-16 03:47:28 +0000 | [diff] [blame] | 2886 | // FIXME: Making this work correctly is nasty because it requires either | 
|  | 2887 | // cloning the body of the call operator or making the call operator forward. | 
|  | 2888 | CGM.ErrorUnsupported(MD, "lambda conversion to variadic function"); | 
| Eli Friedman | 2495ab0 | 2012-02-25 02:48:22 +0000 | [diff] [blame] | 2889 | return; | 
| Eli Friedman | 5b44688 | 2012-02-16 03:47:28 +0000 | [diff] [blame] | 2890 | } | 
|  | 2891 |  | 
| Douglas Gregor | 355efbb | 2012-02-17 03:02:34 +0000 | [diff] [blame] | 2892 | EmitLambdaDelegatingInvokeBody(MD); | 
| Eli Friedman | 5a6d507 | 2012-02-16 01:37:33 +0000 | [diff] [blame] | 2893 | } |