clang: lib/CodeGen/CGExprCXX.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
22#include "llvm/IR/Intrinsics.h"
23
24using namespace clang;
25using namespace CodeGen;
26
27namespace {
28struct MemberCallInfo {
30
31 unsigned PrefixSize;
32};
33}
34
35static MemberCallInfo
37 llvm::Value *This, llvm::Value *ImplicitParam,
40 auto *MD = cast(GD.getDecl());
41
42 assert(CE == nullptr || isa(CE) ||
43 isa(CE));
44 assert(MD->isImplicitObjectMemberFunction() &&
45 "Trying to emit a member or operator call expr on a static method!");
46
47
51
52
53 if (ImplicitParam) {
54 Args.add(RValue::get(ImplicitParam), ImplicitParamTy);
55 }
56
59 unsigned PrefixSize = Args.size() - 1;
60
61
62 if (RtlArgs) {
63
64
65
67 } else if (CE) {
68
69 unsigned ArgsToSkip = 0;
70 if (const auto *Op = dyn_cast(CE)) {
71 if (const auto *M = dyn_cast(Op->getCalleeDecl()))
72 ArgsToSkip =
73 static_cast<unsigned>(!M->isExplicitObjectMemberFunction());
74 }
77 } else {
78 assert(
80 "No CallExpr specified for function with non-zero number of arguments");
81 }
82 return {required, PrefixSize};
83}
84
85RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
87 ReturnValueSlot ReturnValue, llvm::Value *This, llvm::Value *ImplicitParam,
89 llvm::CallBase **CallOrInvoke) {
93 *this, MD, This, ImplicitParam, ImplicitParamTy, CE, Args, RtlArgs);
95 Args, FPT, CallInfo.ReqArgs, CallInfo.PrefixSize);
99}
100
103 llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE,
104 llvm::CallBase **CallOrInvoke) {
106
107 assert(!ThisTy.isNull());
109 "Pointer/Object mixup");
110
113 if (SrcAS != DstAS) {
117 NewType);
118 }
119
122 ImplicitParamTy, CE, Args, nullptr);
127}
128
131 QualType DestroyedType = E->getDestroyedType();
133
134
135
136 Expr *BaseExpr = E->getBase();
139
140
141 if (E->isArrow()) {
144 BaseQuals = PTy->getPointeeType().getQualifiers();
145 } else {
150 }
151
156 break;
157
162 break;
163
166 break;
167 }
168 } else {
169
170
171
172
173
175 }
176
178}
179
185 return cast(Ty->getDecl());
186}
187
188
189
192 llvm::CallBase **CallOrInvoke) {
194
195 if (isa(callee))
197
198 const MemberExpr *ME = cast(callee);
200
202
206 ReturnValue, nullptr, CallOrInvoke);
207 }
208
211 bool IsArrow = ME->isArrow();
213
215 HasQualifier, Qualifier, IsArrow,
216 Base, CallOrInvoke);
217}
218
222 const Expr *Base, llvm::CallBase **CallOrInvoke) {
223 assert(isa(CE) || isa(CE));
224
225
226 bool CanUseVirtualCall = MD->isVirtual() && !HasQualifier;
227
228 const CXXMethodDecl *DevirtualizedMethod = nullptr;
229 if (CanUseVirtualCall &&
231 const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType();
233 assert(DevirtualizedMethod);
235 const Expr *Inner = Base->IgnoreParenBaseCasts();
238
239
240
241
242
243 DevirtualizedMethod = nullptr;
244 else if (getCXXRecord(Inner) == DevirtualizedClass)
245
246
247 Base = Inner;
249
250
251
252
253 DevirtualizedMethod = nullptr;
254 }
255 }
256
257 bool TrivialForCodegen =
259 bool TrivialAssignment =
260 TrivialForCodegen &&
263
264
265
268 LValue TrivialAssignmentRHS;
269 if (auto *OCE = dyn_cast(CE)) {
270 if (OCE->isAssignmentOp()) {
271 if (TrivialAssignment) {
273 } else {
274 RtlArgs = &RtlArgStorage;
278 }
279 }
280 }
281
283 if (IsArrow) {
288 BaseInfo, TBAAInfo);
289 } else {
291 }
292
293 if (const CXXConstructorDecl *Ctor = dyn_cast(MD)) {
294
295
296 assert(!RtlArgs);
297 assert(ReturnValue.isNull() && "Constructor shouldn't have return value");
301 nullptr,
302 QualType(), CE, Args, nullptr);
303
305 false, This.getAddress(), Args,
307 false, CallOrInvoke);
309 }
310
311 if (TrivialForCodegen) {
312 if (isa(MD))
314
315 if (TrivialAssignment) {
316
317
318
319
320
321 LValue RHS = isa(CE)
322 ? TrivialAssignmentRHS
326 }
327
329 "unknown trivial member function");
330 }
331
332
334 DevirtualizedMethod ? DevirtualizedMethod : MD;
336 if (const auto *Dtor = dyn_cast(CalleeDecl))
339 else
341
343
344
345
346
349 if (CE)
351
353 if (const auto *CMCE = dyn_cast(CE)) {
354 auto *IOA = CMCE->getImplicitObjectArgument();
356 if (IsImplicitObjectCXXThis)
357 SkippedChecks.set(SanitizerKind::Alignment, true);
358 if (IsImplicitObjectCXXThis || isa(IOA))
359 SkippedChecks.set(SanitizerKind::Null, true);
360 }
361
364 This.emitRawPointer(*this),
365 C.getRecordType(CalleeDecl->getParent()),
367
368
369
370
371
372
373
374 bool UseVirtualCall = CanUseVirtualCall && !DevirtualizedMethod;
375
376 if (const CXXDestructorDecl *Dtor = dyn_cast(CalleeDecl)) {
378 "Destructor shouldn't have explicit parameters");
379 assert(ReturnValue.isNull() && "Destructor shouldn't have return value");
380 if (UseVirtualCall) {
383 cast(CE), CallOrInvoke);
384 } else {
387 if (getLangOpts().AppleKext && Dtor->isVirtual() && HasQualifier)
389 else if (!DevirtualizedMethod)
392 else {
394 }
395
397 IsArrow ? Base->getType()->getPointeeType() : Base->getType();
399 nullptr,
400 QualType(), CE, CallOrInvoke);
401 }
403 }
404
405
406
407
409 if (UseVirtualCall) {
411 } else {
412 if (SanOpts.has(SanitizerKind::CFINVCall) &&
414 llvm::Value *VTable;
417 *this, This.getAddress(), CalleeDecl->getParent());
419 }
420
423 else if (!DevirtualizedMethod)
426 else {
430 }
431 }
432
436 *this, CalleeDecl, This.getAddress(), UseVirtualCall);
437 This.setAddress(NewThisAddr);
438 }
439
442 nullptr, QualType(), CE, RtlArgs, CallOrInvoke);
443}
444
448 llvm::CallBase **CallOrInvoke) {
450 cast(E->getCallee()->IgnoreParens());
452 const Expr *MemFnExpr = BO->getRHS();
453
456 const auto *RD =
457 cast(MPT->getClass()->castAs<RecordType>()->getDecl());
458
459
461 if (BO->getOpcode() == BO_PtrMemI)
463 else
465
467 QualType(MPT->getClass(), 0));
468
469
471
472
473 llvm::Value *ThisPtrForCall = nullptr;
476 ThisPtrForCall, MemFnPtr, MPT);
477
479
482
483
485
487
488
491 0),
494}
495
498 ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke) {
500 "Trying to emit a member call expr on a static method!");
502 E, MD, ReturnValue, false, nullptr,
503 false, E->getArg(0), CallOrInvoke);
504}
505
508 llvm::CallBase **CallOrInvoke) {
510 CallOrInvoke);
511}
512
516 if (Base->isEmpty())
517 return;
518
520
523
524
525
526
529
530
532 std::vector VBPtrOffsets =
534 for (CharUnits VBPtrOffset : VBPtrOffsets) {
535
536 if (VBPtrOffset >= NVSize)
537 break;
538 std::pair<CharUnits, CharUnits> LastStore = Stores.pop_back_val();
539 CharUnits LastStoreOffset = LastStore.first;
540 CharUnits LastStoreSize = LastStore.second;
541
542 CharUnits SplitBeforeOffset = LastStoreOffset;
543 CharUnits SplitBeforeSize = VBPtrOffset - SplitBeforeOffset;
544 assert(!SplitBeforeSize.isNegative() && "negative store size!");
545 if (!SplitBeforeSize.isZero())
546 Stores.emplace_back(SplitBeforeOffset, SplitBeforeSize);
547
548 CharUnits SplitAfterOffset = VBPtrOffset + VBPtrWidth;
549 CharUnits SplitAfterSize = LastStoreSize - SplitAfterOffset;
550 assert(!SplitAfterSize.isNegative() && "negative store size!");
551 if (!SplitAfterSize.isZero())
552 Stores.emplace_back(SplitAfterOffset, SplitAfterSize);
553 }
554
555
556
557
558
559
560
562 if (!NullConstantForBase->isNullValue()) {
563 llvm::GlobalVariable *NullVariable = new llvm::GlobalVariable(
564 CGF.CGM.getModule(), NullConstantForBase->getType(),
565 true, llvm::GlobalVariable::PrivateLinkage,
566 NullConstantForBase, Twine());
567
570 NullVariable->setAlignment(Align.getAsAlign());
571
573
574
575 for (std::pair<CharUnits, CharUnits> Store : Stores) {
576 CharUnits StoreOffset = Store.first;
577 CharUnits StoreSize = Store.second;
578 llvm::Value *StoreSizeVal = CGF.CGM.getSize(StoreSize);
582 StoreSizeVal);
583 }
584
585
586
587
588 } else {
589 for (std::pair<CharUnits, CharUnits> Store : Stores) {
590 CharUnits StoreOffset = Store.first;
591 CharUnits StoreSize = Store.second;
592 llvm::Value *StoreSizeVal = CGF.CGM.getSize(StoreSize);
595 CGF.Builder.getInt8(0), StoreSizeVal);
596 }
597 }
598}
599
600void
603 assert(!Dest.isIgnored() && "Must have a destination!");
605
606
607
608
609
610 if (E->requiresZeroInitialization() && !Dest.isZeroed()) {
611 switch (E->getConstructionKind()) {
615 break;
620 break;
621 }
622 }
623
624
626 return;
627
628
629 if (getLangOpts().ElideConstructors && E->isElidable()) {
630
631
632
633
634
635 const Expr *SrcObj = E->getArg(0);
637 assert(
640 return;
641 }
642
647 } else {
649 bool ForVirtualBase = false;
651
652 switch (E->getConstructionKind()) {
654
657 break;
658
661 break;
662
664 ForVirtualBase = true;
665 [[fallthrough]];
666
669 }
670
671
673 }
674}
675
677 const Expr *Exp) {
679 Exp = E->getSubExpr();
680 assert(isa(Exp) &&
681 "EmitSynthesizedCXXCopyCtor - unknown copy ctor expr");
684 RunCleanupsScope Scope(*this);
685
686
687
688
689
690 if (E->requiresZeroInitialization())
692
694 && "EmitSynthesizedCXXCopyCtor - Copied-in Array");
696}
697
700 if (->isArray())
702
703
704
705 if (E->getOperatorNew()->isReservedGlobalPlacementOperator())
707
709}
710
713 unsigned minElements,
714 llvm::Value *&numElements,
715 llvm::Value *&sizeWithoutCookie) {
717
720 sizeWithoutCookie
722 return sizeWithoutCookie;
723 }
724
725
726 unsigned sizeWidth = CGF.SizeTy->getBitWidth();
727
728
729 llvm::APInt cookieSize(sizeWidth,
731
732
733
734
735 numElements =
737 if (!numElements)
739 assert(isallvm::IntegerType(numElements->getType()));
740
741
742
743
744
745
746
747 bool isSigned
748 = (*e->getArraySize())->getType()->isSignedIntegerOrEnumerationType();
749 llvm::IntegerType *numElementsType
750 = castllvm::IntegerType(numElements->getType());
751 unsigned numElementsWidth = numElementsType->getBitWidth();
752
753
754 llvm::APInt arraySizeMultiplier(sizeWidth, 1);
757 type = CAT->getElementType();
758 arraySizeMultiplier *= CAT->getSize();
759 }
760
762 llvm::APInt typeSizeMultiplier(sizeWidth, typeSize.getQuantity());
763 typeSizeMultiplier *= arraySizeMultiplier;
764
765
766 llvm::Value *size;
767
768
769
770 if (llvm::ConstantInt *numElementsC =
771 dyn_castllvm::ConstantInt(numElements)) {
772 const llvm::APInt &count = numElementsC->getValue();
773
774 bool hasAnyOverflow = false;
775
776
777 if (isSigned && count.isNegative())
778 hasAnyOverflow = true;
779
780
781
782
783 else if (numElementsWidth > sizeWidth &&
784 numElementsWidth - sizeWidth > count.countl_zero())
785 hasAnyOverflow = true;
786
787
788 llvm::APInt adjustedCount = count.zextOrTrunc(sizeWidth);
789
790
791
792 if (adjustedCount.ult(minElements))
793 hasAnyOverflow = true;
794
795
796
797
798 numElements = llvm::ConstantInt::get(CGF.SizeTy,
799 adjustedCount * arraySizeMultiplier);
800
801
802 bool overflow;
803 llvm::APInt allocationSize
804 = adjustedCount.umul_ov(typeSizeMultiplier, overflow);
805 hasAnyOverflow |= overflow;
806
807
808 if (cookieSize != 0) {
809
810
811 sizeWithoutCookie = llvm::ConstantInt::get(CGF.SizeTy, allocationSize);
812
813 allocationSize = allocationSize.uadd_ov(cookieSize, overflow);
814 hasAnyOverflow |= overflow;
815 }
816
817
818 if (hasAnyOverflow) {
819 size = llvm::Constant::getAllOnesValue(CGF.SizeTy);
820 } else {
821 size = llvm::ConstantInt::get(CGF.SizeTy, allocationSize);
822 }
823
824
825 } else {
826
827
828
829
830
831
832
833
834
835
836
837
838
839 llvm::Value *hasOverflow = nullptr;
840
841
842
843
844 if (numElementsWidth > sizeWidth) {
845 llvm::APInt threshold =
846 llvm::APInt::getOneBitSet(numElementsWidth, sizeWidth);
847
848 llvm::Value *thresholdV
849 = llvm::ConstantInt::get(numElementsType, threshold);
850
851 hasOverflow = CGF.Builder.CreateICmpUGE(numElements, thresholdV);
852 numElements = CGF.Builder.CreateTrunc(numElements, CGF.SizeTy);
853
854
855 } else if (isSigned) {
856 if (numElementsWidth < sizeWidth)
857 numElements = CGF.Builder.CreateSExt(numElements, CGF.SizeTy);
858
859
860
861
862
863
864 if (typeSizeMultiplier == 1)
865 hasOverflow = CGF.Builder.CreateICmpSLT(numElements,
866 llvm::ConstantInt::get(CGF.SizeTy, minElements));
867
868
869 } else if (numElementsWidth < sizeWidth) {
870 numElements = CGF.Builder.CreateZExt(numElements, CGF.SizeTy);
871 }
872
873 assert(numElements->getType() == CGF.SizeTy);
874
875 if (minElements) {
876
877 if (!hasOverflow) {
878 hasOverflow = CGF.Builder.CreateICmpULT(numElements,
879 llvm::ConstantInt::get(CGF.SizeTy, minElements));
880 } else if (numElementsWidth > sizeWidth) {
881
882
883
884 hasOverflow = CGF.Builder.CreateOr(hasOverflow,
885 CGF.Builder.CreateICmpULT(numElements,
886 llvm::ConstantInt::get(CGF.SizeTy, minElements)));
887 }
888 }
889
890 size = numElements;
891
892
893
894
895
896
897
898
899 if (typeSizeMultiplier != 1) {
900 llvm::Function *umul_with_overflow
902
903 llvm::Value *tsmV =
904 llvm::ConstantInt::get(CGF.SizeTy, typeSizeMultiplier);
905 llvm::Value *result =
906 CGF.Builder.CreateCall(umul_with_overflow, {size, tsmV});
907
908 llvm::Value *overflowed = CGF.Builder.CreateExtractValue(result, 1);
909 if (hasOverflow)
910 hasOverflow = CGF.Builder.CreateOr(hasOverflow, overflowed);
911 else
912 hasOverflow = overflowed;
913
914 size = CGF.Builder.CreateExtractValue(result, 0);
915
916
917 if (arraySizeMultiplier != 1) {
918
919
920 if (typeSize.isOne()) {
921 assert(arraySizeMultiplier == typeSizeMultiplier);
922 numElements = size;
923
924
925 } else {
926 llvm::Value *asmV =
927 llvm::ConstantInt::get(CGF.SizeTy, arraySizeMultiplier);
928 numElements = CGF.Builder.CreateMul(numElements, asmV);
929 }
930 }
931 } else {
932
933 assert(arraySizeMultiplier == 1);
934 }
935
936
937 if (cookieSize != 0) {
938 sizeWithoutCookie = size;
939
940 llvm::Function *uadd_with_overflow
942
943 llvm::Value *cookieSizeV = llvm::ConstantInt::get(CGF.SizeTy, cookieSize);
944 llvm::Value *result =
945 CGF.Builder.CreateCall(uadd_with_overflow, {size, cookieSizeV});
946
947 llvm::Value *overflowed = CGF.Builder.CreateExtractValue(result, 1);
948 if (hasOverflow)
949 hasOverflow = CGF.Builder.CreateOr(hasOverflow, overflowed);
950 else
951 hasOverflow = overflowed;
952
953 size = CGF.Builder.CreateExtractValue(result, 0);
954 }
955
956
957
958
959 if (hasOverflow)
960 size = CGF.Builder.CreateSelect(hasOverflow,
961 llvm::Constant::getAllOnesValue(CGF.SizeTy),
962 size);
963 }
964
965 if (cookieSize == 0)
966 sizeWithoutCookie = size;
967 else
968 assert(sizeWithoutCookie && "didn't set sizeWithoutCookie?");
969
970 return size;
971}
972
976
981 return;
984 true);
985 return;
995 return;
996 }
997 }
998 llvm_unreachable("bad evaluation kind");
999}
1000
1003 Address BeginPtr, llvm::Value *NumElements,
1004 llvm::Value *AllocSizeWithoutCookie) {
1005
1006
1007 if (->hasInitializer())
1008 return;
1009
1010 Address CurPtr = BeginPtr;
1011
1012 unsigned InitListElements = 0;
1013
1014 const Expr *Init = E->getInitializer();
1017 CleanupDeactivationScope deactivation(*this);
1018 bool pushedCleanup = false;
1019
1023
1024
1025 auto TryMemsetInitialization = [&]() -> bool {
1026
1027
1029 return false;
1030
1031
1032
1033
1034
1035 auto *RemainingSize = AllocSizeWithoutCookie;
1036 if (InitListElements) {
1037
1038 auto *InitializedSize = llvm::ConstantInt::get(
1039 RemainingSize->getType(),
1040 getContext().getTypeSizeInChars(ElementType).getQuantity() *
1041 InitListElements);
1042 RemainingSize = Builder.CreateSub(RemainingSize, InitializedSize);
1043 }
1044
1045
1047 return true;
1048 };
1049
1054 const Expr *IgnoreParen = nullptr;
1055 if (!ILE) {
1056 IgnoreParen = Init->IgnoreParenImpCasts();
1057 CPLIE = dyn_cast(IgnoreParen);
1058 SL = dyn_cast(IgnoreParen);
1059 OCEE = dyn_cast(IgnoreParen);
1060 }
1061
1062
1063 if (ILE || CPLIE || SL || OCEE) {
1064
1065
1067 if (!ILE)
1068 Init = IgnoreParen;
1069
1070
1071
1081
1082
1083 InitListElements =
1084 cast(Init->getType()->getAsArrayTypeUnsafe())
1085 ->getZExtSize();
1087 CurPtr, InitListElements, "string.init.end");
1088
1089
1090 llvm::ConstantInt *ConstNum = dyn_castllvm::ConstantInt(NumElements);
1091 if (!ConstNum || !ConstNum->equalsInt(InitListElements)) {
1092 bool OK = TryMemsetInitialization();
1093 (void)OK;
1094 assert(OK && "couldn't memset character type?");
1095 }
1096 return;
1097 }
1098
1101 InitListElements = InitExprs.size();
1102
1103
1104
1105 QualType AllocType = E->getAllocatedType();
1106 if (const ConstantArrayType *CAT = dyn_cast_or_null(
1111 }
1112
1113
1114 if (DtorKind) {
1115 AllocaTrackerRAII AllocaTracker(*this);
1116
1117
1118
1119
1120 llvm::Instruction *DominatingIP =
1123 "array.init.end");
1125 EndOfInit, ElementType, ElementAlign,
1128 .AddAuxAllocas(AllocaTracker.Take());
1131 pushedCleanup = true;
1132 }
1133
1135 unsigned i = 0;
1136 for (const Expr *IE : InitExprs) {
1137
1138
1139
1140 if (EndOfInit.isValid()) {
1142 }
1143
1144
1145
1151 "array.exp.next"),
1154 }
1155
1156
1158
1159
1160
1161
1162 while (Init && Init->getType()->isConstantArrayType()) {
1163 auto *SubILE = dyn_cast(Init);
1164 if (!SubILE)
1165 break;
1166 assert(SubILE->getNumInits() == 0 && "explicit inits in array filler?");
1167 Init = SubILE->getArrayFiller();
1168 }
1169
1170
1172 }
1173
1174
1175
1176 llvm::ConstantInt *ConstNum = dyn_castllvm::ConstantInt(NumElements);
1177 if (ConstNum && ConstNum->getZExtValue() <= InitListElements) {
1178 return;
1179 }
1180
1181 assert(Init && "have trailing elements to initialize but no initializer");
1182
1183
1184
1188
1189
1190 if (!CCE->requiresZeroInitialization() || Ctor->getParent()->isEmpty())
1191 return;
1192
1193 if (TryMemsetInitialization())
1194 return;
1195 }
1196
1197
1198
1199
1200
1201 if (EndOfInit.isValid())
1203
1204
1205 if (InitListElements)
1206 NumElements = Builder.CreateSub(
1207 NumElements,
1208 llvm::ConstantInt::get(NumElements->getType(), InitListElements));
1210 true,
1211 CCE->requiresZeroInitialization());
1212 return;
1213 }
1214
1215
1217 if (isa(Init)) {
1218 if (TryMemsetInitialization())
1219 return;
1220
1221
1222
1223
1224 Init = &IVIE;
1225 }
1226
1227
1228
1229 assert(getContext().hasSameUnqualifiedType(ElementType, Init->getType()) &&
1230 "got wrong type of element to initialize");
1231
1232
1233 if (auto *ILE = dyn_cast(Init))
1234 if (ILE->getNumInits() == 0 && TryMemsetInitialization())
1235 return;
1236
1237
1238
1239 if (auto *ILE = dyn_cast(Init)) {
1241 if (RType->getDecl()->isStruct()) {
1242 unsigned NumElements = 0;
1243 if (auto *CXXRD = dyn_cast(RType->getDecl()))
1244 NumElements = CXXRD->getNumBases();
1245 for (auto *Field : RType->getDecl()->fields())
1246 if (->isUnnamedBitField())
1247 ++NumElements;
1248
1250 for (unsigned i = 0, e = ILE->getNumInits(); i != e; ++i)
1251 if (!isa(ILE->getInit(i)))
1252 --NumElements;
1253 if (ILE->getNumInits() == NumElements && TryMemsetInitialization())
1254 return;
1255 }
1256 }
1257 }
1258
1259
1260 llvm::BasicBlock *EntryBB = Builder.GetInsertBlock();
1262 llvm::BasicBlock *ContBB = createBasicBlock("new.loop.end");
1263
1264
1267 "array.end");
1268
1269
1270
1271 if (!ConstNum) {
1273 EndPtr, "array.isempty");
1274 Builder.CreateCondBr(IsEmpty, ContBB, LoopBB);
1275 }
1276
1277
1279
1280
1281 llvm::PHINode *CurPtrPhi =
1282 Builder.CreatePHI(CurPtr.getType(), 2, "array.cur");
1283 CurPtrPhi->addIncoming(CurPtr.emitRawPointer(*this), EntryBB);
1284
1286
1287
1288 if (EndOfInit.isValid())
1290
1291
1293 llvm::Instruction *DominatingIP =
1300 }
1301
1302
1305
1306
1307 deactivation.ForceDeactivate();
1308
1309
1310 llvm::Value *NextPtr = Builder.CreateConstInBoundsGEP1_32(
1311 ElementTy, CurPtr.emitRawPointer(*this), 1, "array.next");
1312
1313
1314
1315 llvm::Value *IsEnd = Builder.CreateICmpEQ(NextPtr, EndPtr, "array.atend");
1316 Builder.CreateCondBr(IsEnd, ContBB, LoopBB);
1317 CurPtrPhi->addIncoming(NextPtr, Builder.GetInsertBlock());
1318
1320}
1321
1323 QualType ElementType, llvm::Type *ElementTy,
1324 Address NewPtr, llvm::Value *NumElements,
1325 llvm::Value *AllocSizeWithoutCookie) {
1327 if (E->isArray())
1329 AllocSizeWithoutCookie);
1330 else if (const Expr *Init = E->getInitializer())
1333}
1334
1335
1336
1341 llvm::CallBase *CallOrInvoke;
1346 Args, CalleeType, false),
1348
1349
1350
1351
1352
1353
1354 llvm::Function *Fn = dyn_castllvm::Function(CalleePtr);
1356 Fn && Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
1357 CallOrInvoke->addFnAttr(llvm::Attribute::Builtin);
1358 }
1359
1360 return RV;
1361}
1362
1365 bool IsDelete) {
1368
1372
1374 if (auto *FD = dyn_cast(Decl))
1377 llvm_unreachable("predeclared global operator new/delete is missing");
1378}
1379
1380namespace {
1381
1382struct UsualDeleteParams {
1383 bool DestroyingDelete = false;
1384 bool Size = false;
1385 bool Alignment = false;
1386};
1387}
1388
1390 UsualDeleteParams Params;
1391
1394
1395
1396 ++AI;
1397
1398
1400 Params.DestroyingDelete = true;
1401 assert(AI != AE);
1402 ++AI;
1403 }
1404
1405
1407 Params.Size = true;
1408 ++AI;
1409 }
1410
1412 Params.Alignment = true;
1413 ++AI;
1414 }
1415
1416 assert(AI == AE && "unexpected usual deallocation function parameter");
1417 return Params;
1418}
1419
1420namespace {
1421
1422
1423
1424 template
1426
1427 typedef typename Traits::ValueTy ValueTy;
1428
1429 typedef typename Traits::RValueTy RValueTy;
1430 struct PlacementArg {
1431 RValueTy ArgValue;
1433 };
1434
1435 unsigned NumPlacementArgs : 31;
1436 LLVM_PREFERRED_TYPE(bool)
1437 unsigned PassAlignmentToPlacementDelete : 1;
1439 ValueTy Ptr;
1440 ValueTy AllocSize;
1442
1443 PlacementArg *getPlacementArgs() {
1444 return reinterpret_cast<PlacementArg *>(this + 1);
1445 }
1446
1447 public:
1448 static size_t getExtraSize(size_t NumPlacementArgs) {
1449 return NumPlacementArgs * sizeof(PlacementArg);
1450 }
1451
1452 CallDeleteDuringNew(size_t NumPlacementArgs,
1453 const FunctionDecl *OperatorDelete, ValueTy Ptr,
1454 ValueTy AllocSize, bool PassAlignmentToPlacementDelete,
1456 : NumPlacementArgs(NumPlacementArgs),
1457 PassAlignmentToPlacementDelete(PassAlignmentToPlacementDelete),
1458 OperatorDelete(OperatorDelete), Ptr(Ptr), AllocSize(AllocSize),
1459 AllocAlign(AllocAlign) {}
1460
1461 void setPlacementArg(unsigned I, RValueTy Arg, QualType Type) {
1462 assert(I < NumPlacementArgs && "index out of range");
1463 getPlacementArgs()[I] = {Arg, Type};
1464 }
1465
1467 const auto *FPT = OperatorDelete->getType()->castAs<FunctionProtoType>();
1469
1470
1471
1472 DeleteArgs.add(Traits::get(CGF, Ptr), FPT->getParamType(0));
1473
1474
1475 UsualDeleteParams Params;
1476 if (NumPlacementArgs) {
1477
1478
1479 Params.Alignment = PassAlignmentToPlacementDelete;
1480 } else {
1481
1482
1484 }
1485
1486 assert(!Params.DestroyingDelete &&
1487 "should not call destroying delete in a new-expression");
1488
1489
1490 if (Params.Size)
1491 DeleteArgs.add(Traits::get(CGF, AllocSize),
1493
1494
1495
1496
1497
1498 if (Params.Alignment)
1499 DeleteArgs.add(RValue::get(llvm::ConstantInt::get(
1502
1503
1504 for (unsigned I = 0; I != NumPlacementArgs; ++I) {
1505 auto Arg = getPlacementArgs()[I];
1506 DeleteArgs.add(Traits::get(CGF, Arg.ArgValue), Arg.ArgType);
1507 }
1508
1509
1511 }
1512 };
1513}
1514
1515
1516
1520 llvm::Value *AllocSize,
1523 unsigned NumNonPlacementArgs = E->passAlignment() ? 2 : 1;
1524
1525
1526
1528 struct DirectCleanupTraits {
1529 typedef llvm::Value *ValueTy;
1530 typedef RValue RValueTy;
1533 };
1534
1535 typedef CallDeleteDuringNew DirectCleanup;
1536
1538 EHCleanup, E->getNumPlacementArgs(), E->getOperatorDelete(),
1539 NewPtr.emitRawPointer(CGF), AllocSize, E->passAlignment(), AllocAlign);
1540 for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {
1541 auto &Arg = NewArgs[I + NumNonPlacementArgs];
1542 Cleanup->setPlacementArg(I, Arg.getRValue(CGF), Arg.Ty);
1543 }
1544
1545 return;
1546 }
1547
1548
1553
1554 struct ConditionalCleanupTraits {
1558 return V.restore(CGF);
1559 }
1560 };
1561 typedef CallDeleteDuringNew ConditionalCleanup;
1562
1563 ConditionalCleanup *Cleanup = CGF.EHStack
1565 E->getNumPlacementArgs(),
1566 E->getOperatorDelete(),
1567 SavedNewPtr,
1568 SavedAllocSize,
1569 E->passAlignment(),
1570 AllocAlign);
1571 for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {
1572 auto &Arg = NewArgs[I + NumNonPlacementArgs];
1573 Cleanup->setPlacementArg(
1575 }
1576
1578}
1579
1581
1583
1584
1586
1587
1588
1589 unsigned minElements = 0;
1590 if (E->isArray() && E->hasInitializer()) {
1591 const Expr *Init = E->getInitializer();
1594 const Expr *IgnoreParen = Init->IgnoreParenImpCasts();
1596 isa(IgnoreParen) || isa(IgnoreParen)) {
1597 minElements =
1598 cast(Init->getType()->getAsArrayTypeUnsafe())
1599 ->getZExtSize();
1600 } else if (ILE || CPLIE) {
1602 }
1603 }
1604
1605 llvm::Value *numElements = nullptr;
1606 llvm::Value *allocSizeWithoutCookie = nullptr;
1607 llvm::Value *allocSize =
1609 allocSizeWithoutCookie);
1611
1612
1613
1617 assert(E->getNumPlacementArgs() == 1);
1618 const Expr *arg = *E->placement_arguments().begin();
1619
1622
1623
1624
1625
1628
1629
1630
1631 if (E->getOperatorDelete() &&
1632 ->getOperatorDelete()->isReservedGlobalPlacementOperator()) {
1634 allocatorArgs.add(RValue::get(allocation, *this), arg->getType());
1635 }
1636
1637 } else {
1640 unsigned ParamsToSkip = 0;
1641
1642
1644 allocatorArgs.add(RValue::get(allocSize), sizeType);
1645 ++ParamsToSkip;
1646
1647 if (allocSize != allocSizeWithoutCookie) {
1649 allocAlign = std::max(allocAlign, cookieAlign);
1650 }
1651
1652
1653 if (E->passAlignment()) {
1654 QualType AlignValT = sizeType;
1657 assert(getContext().hasSameUnqualifiedType(
1659 sizeType) &&
1660 "wrong type for alignment parameter");
1661 ++ParamsToSkip;
1662 } else {
1663
1664 assert(allocator->isVariadic() && "can't pass alignment to allocator");
1665 }
1666 allocatorArgs.add(
1668 AlignValT);
1669 }
1670
1671
1672 EmitCallArgs(allocatorArgs, allocatorType, E->placement_arguments(),
1673 AbstractCallee(), ParamsToSkip);
1674
1676 EmitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs);
1677
1678
1680 if (auto *newCall = dyn_castllvm::CallBase(RV.getScalarVal()))
1683
1684
1685
1686
1687
1688 CharUnits allocationAlign = allocAlign;
1689 if (->passAlignment() &&
1691 unsigned AllocatorAlign = llvm::bit_floor(std::min<uint64_t>(
1693 allocationAlign = std::max(
1694 allocationAlign, getContext().toCharUnitsFromBits(AllocatorAlign));
1695 }
1696
1698 }
1699
1700
1701
1702
1703
1704 bool nullCheck = E->shouldNullCheckAllocation() &&
1707
1708 llvm::BasicBlock *nullCheckBB = nullptr;
1709 llvm::BasicBlock *contBB = nullptr;
1710
1711
1712
1713 ConditionalEvaluation conditional(*this);
1714
1715 if (nullCheck) {
1716 conditional.begin(*this);
1717
1718 nullCheckBB = Builder.GetInsertBlock();
1719 llvm::BasicBlock *notNullBB = createBasicBlock("new.notnull");
1721
1723 Builder.CreateCondBr(isNull, contBB, notNullBB);
1725 }
1726
1727
1728
1730 llvm::Instruction *cleanupDominator = nullptr;
1731 if (E->getOperatorDelete() &&
1732 ->getOperatorDelete()->isReservedGlobalPlacementOperator()) {
1734 allocatorArgs);
1736 cleanupDominator = Builder.CreateUnreachable();
1737 }
1738
1739 assert((allocSize == allocSizeWithoutCookie) ==
1741 if (allocSize != allocSizeWithoutCookie) {
1742 assert(E->isArray());
1744 numElements,
1745 E, allocType);
1746 }
1747
1750
1751
1752
1753
1754
1758
1759
1760
1761
1762
1763
1765 SkippedChecks.set(SanitizerKind::Null, nullCheck);
1767 E->getAllocatedTypeSourceInfo()->getTypeLoc().getBeginLoc(),
1768 result, allocType, result.getAlignment(), SkippedChecks,
1769 numElements);
1770
1772 allocSizeWithoutCookie);
1773 llvm::Value *resultPtr = result.emitRawPointer(*this);
1774
1775
1776
1777 if (operatorDeleteCleanup.isValid()) {
1779 cleanupDominator->eraseFromParent();
1780 }
1781
1782 if (nullCheck) {
1783 conditional.end(*this);
1784
1785 llvm::BasicBlock *notNullBB = Builder.GetInsertBlock();
1787
1788 llvm::PHINode *PHI = Builder.CreatePHI(resultPtr->getType(), 2);
1789 PHI->addIncoming(resultPtr, notNullBB);
1790 PHI->addIncoming(llvm::Constant::getNullValue(resultPtr->getType()),
1791 nullCheckBB);
1792
1793 resultPtr = PHI;
1794 }
1795
1796 return resultPtr;
1797}
1798
1800 llvm::Value *DeletePtr, QualType DeleteTy,
1801 llvm::Value *NumElements,
1803 assert((!NumElements && CookieSize.isZero()) ||
1805
1808
1810 auto ParamTypeIt = DeleteFTy->param_type_begin();
1811
1812
1813 QualType ArgTy = *ParamTypeIt++;
1814 DeleteArgs.add(RValue::get(DeletePtr), ArgTy);
1815
1816
1817 llvm::AllocaInst *DestroyingDeleteTag = nullptr;
1818 if (Params.DestroyingDelete) {
1819 QualType DDTag = *ParamTypeIt++;
1822 DestroyingDeleteTag = CreateTempAlloca(Ty, "destroying.delete.tag");
1823 DestroyingDeleteTag->setAlignment(Align.getAsAlign());
1824 DeleteArgs.add(
1826 }
1827
1828
1829 if (Params.Size) {
1830 QualType SizeType = *ParamTypeIt++;
1832 llvm::Value *Size = llvm::ConstantInt::get(ConvertType(SizeType),
1834
1835
1836 if (NumElements)
1837 Size = Builder.CreateMul(Size, NumElements);
1838
1839
1840 if (!CookieSize.isZero())
1842 Size, llvm::ConstantInt::get(SizeTy, CookieSize.getQuantity()));
1843
1844 DeleteArgs.add(RValue::get(Size), SizeType);
1845 }
1846
1847
1848 if (Params.Alignment) {
1849 QualType AlignValType = *ParamTypeIt++;
1852 DeleteTy, true ));
1853 llvm::Value *Align = llvm::ConstantInt::get(ConvertType(AlignValType),
1855 DeleteArgs.add(RValue::get(Align), AlignValType);
1856 }
1857
1858 assert(ParamTypeIt == DeleteFTy->param_type_end() &&
1859 "unknown parameter to usual delete function");
1860
1861
1863
1864
1865
1866 if (DestroyingDeleteTag && DestroyingDeleteTag->use_empty())
1867 DestroyingDeleteTag->eraseFromParent();
1868}
1869
1870namespace {
1871
1873 llvm::Value *Ptr;
1876
1877 CallObjectDelete(llvm::Value *Ptr,
1880 : Ptr(Ptr), OperatorDelete(OperatorDelete), ElementType(ElementType) {}
1881
1883 CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType);
1884 }
1885 };
1886}
1887
1888void
1890 llvm::Value *CompletePtr,
1893 OperatorDelete, ElementType);
1894}
1895
1896
1897
1898
1899
1904 if (Dtor && Dtor->isVirtual())
1906 Dtor);
1907 else
1909 ElementType);
1910}
1911
1912
1913
1914
1919 llvm::BasicBlock *UnconditionalDeleteBlock) {
1920
1921
1922
1923
1924
1926 ElementType);
1927
1929 assert(!OperatorDelete->isDestroyingOperatorDelete());
1930
1931
1932
1935 CXXRecordDecl *RD = cast(RT->getDecl());
1938
1940 bool UseVirtualCall = true;
1942 if (auto *DevirtualizedDtor =
1943 dyn_cast_or_null(
1946 UseVirtualCall = false;
1950
1951
1952 Dtor = DevirtualizedDtor;
1953 } else {
1954
1955
1956
1957
1958
1959 UseVirtualCall = true;
1960 }
1961 }
1962 if (UseVirtualCall) {
1964 Dtor);
1965 return false;
1966 }
1967 }
1968 }
1969 }
1970
1971
1972
1973
1974 CGF.EHStack.pushCleanup(
1976
1977 if (Dtor)
1979 false,
1980 false,
1981 Ptr, ElementType);
1982 else if (auto Lifetime = ElementType.getObjCLifetime()) {
1983 switch (Lifetime) {
1987 break;
1988
1991 break;
1992
1995 break;
1996 }
1997 }
1998
1999
2001 CGF.EmitBlock(UnconditionalDeleteBlock);
2003 return true;
2004 }
2005
2007 return false;
2008}
2009
2010namespace {
2011
2013 llvm::Value *Ptr;
2015 llvm::Value *NumElements;
2018
2019 CallArrayDelete(llvm::Value *Ptr,
2021 llvm::Value *NumElements,
2024 : Ptr(Ptr), OperatorDelete(OperatorDelete), NumElements(NumElements),
2025 ElementType(ElementType), CookieSize(CookieSize) {}
2026
2028 CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType, NumElements,
2029 CookieSize);
2030 }
2031 };
2032}
2033
2034
2039 llvm::Value *numElements = nullptr;
2040 llvm::Value *allocatedPtr = nullptr;
2043 numElements, allocatedPtr, cookieSize);
2044
2045 assert(allocatedPtr && "ReadArrayCookie didn't set allocated pointer");
2046
2047
2048 const FunctionDecl *operatorDelete = E->getOperatorDelete();
2050 allocatedPtr, operatorDelete,
2051 numElements, elementType,
2052 cookieSize);
2053
2054
2056 assert(numElements && "no element count for a type with a destructor!");
2057
2061
2062 llvm::Value *arrayBegin = deletedPtr.emitRawPointer(CGF);
2064 deletedPtr.getElementType(), arrayBegin, numElements, "delete.end");
2065
2066
2067
2068
2069 CGF.emitArrayDestroy(arrayBegin, arrayEnd, elementType, elementAlign,
2071 true,
2073 }
2074
2075
2077}
2078
2080 const Expr *Arg = E->getArgument();
2082
2083
2084
2085
2086
2087
2088
2089
2090 llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull");
2091 llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end");
2092
2094
2095 Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull);
2098
2099 QualType DeleteTy = E->getDestroyedType();
2100
2101
2102
2103 if (E->getOperatorDelete()->isDestroyingOperatorDelete()) {
2106 return;
2107 }
2108
2109
2110
2111
2113 llvm::Value *Zero = Builder.getInt32(0);
2115
2116 GEP.push_back(Zero);
2117
2118
2120 = getContext().getAsConstantArrayType(DeleteTy)) {
2121
2122 DeleteTy = Arr->getElementType();
2123
2124
2125 GEP.push_back(Zero);
2126 }
2127
2130 }
2131
2133
2134 if (E->isArrayForm()) {
2137 } else {
2140 }
2141}
2142
2144 llvm::Type *StdTypeInfoPtrTy,
2145 bool HasNullCheck) {
2146
2148
2150
2151
2152
2153
2154
2156 ThisPtr, SrcRecordTy);
2157
2158
2159
2160
2161 if (HasNullCheck &&
2163 llvm::BasicBlock *BadTypeidBlock =
2165 llvm::BasicBlock *EndBlock = CGF.createBasicBlock("typeid.end");
2166
2168 CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock);
2169
2173 }
2174
2176 StdTypeInfoPtrTy);
2177}
2178
2180
2181
2182
2183
2184
2187
2188 auto MaybeASCast = [=](auto &&TypeInfo) {
2193 };
2194
2195 if (E->isTypeOperand()) {
2198 return MaybeASCast(TypeInfo);
2199 }
2200
2201
2202
2203
2204
2205
2206
2207 if (E->isPotentiallyEvaluated() && ->isMostDerived(getContext()))
2209 E->hasNullCheck());
2210
2213}
2214
2217 llvm::Type *DestLTy = CGF.ConvertType(DestTy);
2219 return llvm::Constant::getNullValue(DestLTy);
2220
2221
2222
2224 return nullptr;
2225
2226 CGF.Builder.ClearInsertionPoint();
2227 return llvm::PoisonValue::get(DestLTy);
2228}
2229
2234
2236
2237
2238
2239
2243 if (IsDynamicCastToVoid) {
2245
2249 } else {
2250 SrcRecordTy = SrcTy;
2252 }
2253
2254
2255
2256
2257
2258
2260
2263
2264 if (.GetInsertBlock())
2266 return T;
2267 }
2268 }
2269
2270 assert(SrcRecordTy->isRecordType() && "source type must be a record type!");
2271
2272
2273
2274 bool IsExact = !IsDynamicCastToVoid &&
2278
2279
2280
2281
2282 bool ShouldNullCheckSrcValue =
2285
2286 llvm::BasicBlock *CastNull = nullptr;
2287 llvm::BasicBlock *CastNotNull = nullptr;
2288 llvm::BasicBlock *CastEnd = createBasicBlock("dynamic_cast.end");
2289
2290 if (ShouldNullCheckSrcValue) {
2293
2295 Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
2297 }
2298
2299 llvm::Value *Value;
2300 if (IsDynamicCastToVoid) {
2302 } else if (IsExact) {
2303
2304
2306 *this, ThisAddr, SrcRecordTy, DestTy, DestRecordTy, CastEnd, CastNull);
2307 } else {
2309 "destination type must be a record type!");
2311 DestTy, DestRecordTy, CastEnd);
2312 }
2313 CastNotNull = Builder.GetInsertBlock();
2314
2315 llvm::Value *NullValue = nullptr;
2316 if (ShouldNullCheckSrcValue) {
2318
2321 CastNull = Builder.GetInsertBlock();
2322
2324 }
2325
2327
2328 if (CastNull) {
2330 PHI->addIncoming(Value, CastNotNull);
2331 PHI->addIncoming(NullValue, CastNull);
2332
2334 }
2335
2337}
static MemberCallInfo commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, GlobalDecl GD, llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE, CallArgList &Args, CallArgList *RtlArgs)
static llvm::Value * EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, llvm::Type *StdTypeInfoPtrTy, bool HasNullCheck)
static llvm::Value * EmitDynamicCastToNull(CodeGenFunction &CGF, QualType DestTy)
static RValue EmitNewDeleteCall(CodeGenFunction &CGF, const FunctionDecl *CalleeDecl, const FunctionProtoType *CalleeType, const CallArgList &Args)
Emit a call to an operator new or operator delete function, as implicitly created by new-expressions ...
static void EmitDestroyingObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, Address Ptr, QualType ElementType)
Emit the code for deleting a single object with a destroying operator delete.
static void EmitNullBaseClassInitialization(CodeGenFunction &CGF, Address DestPtr, const CXXRecordDecl *Base)
static void EnterNewDeleteCleanup(CodeGenFunction &CGF, const CXXNewExpr *E, Address NewPtr, llvm::Value *AllocSize, CharUnits AllocAlign, const CallArgList &NewArgs)
Enter a cleanup to call 'operator delete' if the initializer in a new-expression throws.
static bool EmitObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, Address Ptr, QualType ElementType, llvm::BasicBlock *UnconditionalDeleteBlock)
Emit the code for deleting a single object.
static UsualDeleteParams getUsualDeleteParams(const FunctionDecl *FD)
static CXXRecordDecl * getCXXRecord(const Expr *E)
static CharUnits CalculateCookiePadding(CodeGenFunction &CGF, const CXXNewExpr *E)
static void EmitArrayDelete(CodeGenFunction &CGF, const CXXDeleteExpr *E, Address deletedPtr, QualType elementType)
Emit the code for deleting an array of objects.
static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init, QualType AllocType, Address NewPtr, AggValueSlot::Overlap_t MayOverlap)
static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E, QualType ElementType, llvm::Type *ElementTy, Address NewPtr, llvm::Value *NumElements, llvm::Value *AllocSizeWithoutCookie)
static llvm::Value * EmitCXXNewAllocSize(CodeGenFunction &CGF, const CXXNewExpr *e, unsigned minElements, llvm::Value *&numElements, llvm::Value *&sizeWithoutCookie)
llvm::MachO::Target Target
static QualType getPointeeType(const MemRegion *R)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TranslationUnitDecl * getTranslationUnitDecl() const
const ConstantArrayType * getAsConstantArrayType(QualType T) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
DeclarationNameTable DeclarationNames
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getNonVirtualAlignment() const
getNonVirtualAlignment - Get the non-virtual alignment (in chars) of an object, which is the alignmen...
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
Represents an array type, per C99 6.7.5.2 - Array Declarators.
A builtin binary operation expression such as "x + y" or "x <= y".
Represents a call to a CUDA kernel function.
Represents a call to a C++ constructor.
Represents a C++ constructor within a class.
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Represents a delete expression for memory deallocation and destructor calls, e.g.
FunctionDecl * getOperatorDelete() const
Represents a C++ destructor within a class.
A C++ dynamic_cast expression (C++ [expr.dynamic.cast]).
bool isAlwaysNull() const
isAlwaysNull - Return whether the result of the dynamic_cast is proven to always be null.
Represents a call to a member function that may be written either with member call syntax (e....
Represents a static or instance method of a struct/union/class.
bool isImplicitObjectMemberFunction() const
[C++2b][dcl.fct]/p7 An implicit object member function is a non-static member function without an exp...
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getThisType() const
Return the type of the this pointer.
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
Qualifiers getMethodQualifiers() const
CXXMethodDecl * getDevirtualizedMethod(const Expr *Base, bool IsAppleKext)
If it's possible to devirtualize a call to this method, return the called function.
CXXMethodDecl * getCorrespondingMethodInClass(const CXXRecordDecl *RD, bool MayBeBase=false)
Find the method in RD that corresponds to this one.
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
QualType getAllocatedType() const
std::optional< Expr * > getArraySize()
This might return std::nullopt even if isArray() returns true, since there might not be an array size...
A call to an overloaded operator written using operator syntax.
Represents a list-initialization with parenthesis.
ArrayRef< Expr * > getInitExprs()
Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
Represents a C++ struct/union/class.
bool isEffectivelyFinal() const
Determine whether it's impossible for a class to be derived from this class.
bool hasTrivialDestructor() const
Determine whether this class has a trivial destructor (C++ [class.dtor]p3)
bool isDynamicClass() const
bool hasDefinition() const
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
A C++ typeid expression (C++ [expr.typeid]), which gets the type_info that corresponds to the supplie...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
SourceLocation getBeginLoc() const LLVM_READONLY
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
CharUnits - This is an opaque type for sizes expressed in character units.
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset?
bool isNegative() const
isNegative - Test whether the quantity is less than zero.
bool isZero() const
isZero - Test whether the quantity equals zero.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
bool isOne() const
isOne - Test whether the quantity equals one.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
Address setKnownNonNull()
void setAlignment(CharUnits Value)
llvm::PointerType * getType() const
Return the type of the pointer value.
bool isSanitizerChecked() const
Address getAddress() const
IsZeroed_t isZeroed() const
static AggValueSlot forAddr(Address addr, Qualifiers quals, IsDestructed_t isDestructed, NeedsGCBarriers_t needsGC, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed, IsSanitizerChecked_t isChecked=IsNotSanitizerChecked)
forAddr - Make a slot for an aggregate value.
A scoped helper to set the current debug location to the specified location or preferred location of ...
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name="")
Given a pointer to i8, adjust it by a given constant offset.
llvm::Value * CreateIsNull(Address Addr, const Twine &Name="")
llvm::CallInst * CreateMemSet(Address Dest, llvm::Value *Value, llvm::Value *Size, bool IsVolatile=false)
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::LoadInst * CreateFlagLoad(llvm::Value *Addr, const llvm::Twine &Name="")
Emit a load from an i1 flag variable.
Address CreateLaunderInvariantGroup(Address Addr)
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
llvm::ConstantInt * getSize(CharUnits N)
Address CreateConstInBoundsGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = T* ... produce name = getelementptr inbounds addr, i64 index where i64 is actually the t...
Address CreateInBoundsGEP(Address Addr, ArrayRef< llvm::Value * > IdxList, llvm::Type *ElementType, CharUnits Align, const Twine &Name="")
virtual RValue EmitCUDAKernelCallExpr(CodeGenFunction &CGF, const CUDAKernelCallExpr *E, ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke=nullptr)
virtual bool shouldEmitExactDynamicCast(QualType DestRecordTy)=0
virtual std::vector< CharUnits > getVBPtrOffsets(const CXXRecordDecl *RD)
Gets the offsets of all the virtual base pointers in a given class.
virtual void ReadArrayCookie(CodeGenFunction &CGF, Address Ptr, const CXXDeleteExpr *expr, QualType ElementType, llvm::Value *&NumElements, llvm::Value *&AllocPtr, CharUnits &CookieSize)
Reads the array cookie associated with the given pointer, if it has one.
virtual bool shouldTypeidBeNullChecked(QualType SrcRecordTy)=0
virtual std::pair< llvm::Value *, const CXXRecordDecl * > LoadVTablePtr(CodeGenFunction &CGF, Address This, const CXXRecordDecl *RD)=0
Load a vtable from This, an object of polymorphic type RD, or from one of its virtual bases if it doe...
virtual Address adjustThisArgumentForVirtualFunctionCall(CodeGenFunction &CGF, GlobalDecl GD, Address This, bool VirtualCall)
Perform ABI-specific "this" argument adjustment required prior to a call of a virtual function.
virtual void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, Address Ptr, QualType ElementType, const CXXDestructorDecl *Dtor)=0
virtual llvm::Value * emitExactDynamicCast(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastSuccess, llvm::BasicBlock *CastFail)=0
Emit a dynamic_cast from SrcRecordTy to DestRecordTy.
virtual const CXXRecordDecl * getThisArgumentTypeForMethod(GlobalDecl GD)
Get the type of the implicit "this" parameter used by a method.
virtual bool EmitBadCastCall(CodeGenFunction &CGF)=0
virtual llvm::Value * EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, Address ThisPtr, llvm::Type *StdTypeInfoPtrTy)=0
virtual CGCallee EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E, Address This, llvm::Value *&ThisPtrForCall, llvm::Value *MemPtr, const MemberPointerType *MPT)
Load a member function from an object and a member function pointer.
virtual llvm::Value * EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, Address This, DeleteOrMemberCallExpr E, llvm::CallBase **CallOrInvoke)=0
Emit the ABI-specific virtual destructor call.
virtual CharUnits GetArrayCookieSize(const CXXNewExpr *expr)
Returns the extra size required in order to store the array cookie for the given new-expression.
virtual void EmitBadTypeidCall(CodeGenFunction &CGF)=0
virtual llvm::Value * emitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy)=0
virtual llvm::Value * emitDynamicCastCall(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd)=0
virtual Address InitializeArrayCookie(CodeGenFunction &CGF, Address NewPtr, llvm::Value *NumElements, const CXXNewExpr *expr, QualType ElementType)
Initialize the array cookie for the given allocation.
virtual bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr, QualType SrcRecordTy)=0
All available information about a concrete callee.
static CGCallee forVirtual(const CallExpr *CE, GlobalDecl MD, Address Addr, llvm::FunctionType *FTy)
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
void addHeapAllocSiteMetadata(llvm::CallBase *CallSite, QualType AllocatedTy, SourceLocation Loc)
Add heapallocsite metadata for MSAllocator calls.
CGFunctionInfo - Class to encapsulate the information about a function definition.
CallArgList - Type for representing both the value and type of arguments in a call.
void add(RValue rvalue, QualType type)
void addFrom(const CallArgList &other)
Add all the arguments from another CallArgList to this one.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, Address This, Address Src, const CXXConstructExpr *E)
void pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete, llvm::Value *CompletePtr, QualType ElementType)
void EmitARCDestroyWeak(Address addr)
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
GlobalDecl CurGD
CurGD - The GlobalDecl for the current function being compiled.
void DeactivateCleanupBlock(EHScopeStack::stable_iterator Cleanup, llvm::Instruction *DominatingIP)
DeactivateCleanupBlock - Deactivates the given cleanup block.
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
bool sanitizePerformTypeCheck() const
Whether any type-checking sanitizers are enabled.
SanitizerSet SanOpts
Sanitizers enabled for this function.
void EmitVTablePtrCheckForCall(const CXXRecordDecl *RD, llvm::Value *VTable, CFITypeCheckKind TCK, SourceLocation Loc)
EmitVTablePtrCheckForCall - Virtual method MD is being called via VTable.
RValue EmitCUDAKernelCallExpr(const CUDAKernelCallExpr *E, ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke)
void EmitCallArgs(CallArgList &Args, PrototypeWrapper Prototype, llvm::iterator_range< CallExpr::const_arg_iterator > ArgRange, AbstractCallee AC=AbstractCallee(), unsigned ParamsToSkip=0, EvaluationOrder Order=EvaluationOrder::Default)
RValue EmitCXXMemberOrOperatorCall(const CXXMethodDecl *Method, const CGCallee &Callee, ReturnValueSlot ReturnValue, llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *E, CallArgList *RtlArgs, llvm::CallBase **CallOrInvoke)
void pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin, Address arrayEndPointer, QualType elementType, CharUnits elementAlignment, Destroyer *destroyer)
void EmitSynthesizedCXXCopyCtor(Address Dest, Address Src, const Expr *Exp)
void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, const ArrayType *ArrayTy, Address ArrayPtr, const CXXConstructExpr *E, bool NewPointerIsChecked, bool ZeroInitialization=false)
void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This, QualType ThisTy)
RValue EmitCXXMemberOrOperatorMemberCallExpr(const CallExpr *CE, const CXXMethodDecl *MD, ReturnValueSlot ReturnValue, bool HasQualifier, NestedNameSpecifier *Qualifier, bool IsArrow, const Expr *Base, llvm::CallBase **CallOrInvoke)
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
llvm::SmallVector< DeferredDeactivateCleanup > DeferredDeactivationCleanupStack
void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr, QualType DeleteTy, llvm::Value *NumElements=nullptr, CharUnits CookieSize=CharUnits())
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
RValue EmitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E)
const LangOptions & getLangOpts() const
void emitArrayDestroy(llvm::Value *begin, llvm::Value *end, QualType elementType, CharUnits elementAlign, Destroyer *destroyer, bool checkZeroLength, bool useEHCleanup)
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
@ TCK_ConstructorCall
Checking the 'this' pointer for a constructor call.
@ TCK_MemberCall
Checking the 'this' pointer for a call to a non-static member function.
@ TCK_DynamicOperation
Checking the operand of a dynamic_cast or a typeid expression.
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
llvm::Type * ConvertTypeForMem(QualType T)
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
void EmitScalarInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
@ ForceRightToLeft
! Language semantics require right-to-left evaluation.
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
void EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType, llvm::Type *ElementTy, Address NewPtr, llvm::Value *NumElements, llvm::Value *AllocSizeWithoutCookie)
void initFullExprCleanup()
Set up the last cleanup that was pushed as a conditional full-expression cleanup.
bool isInConditionalBranch() const
isInConditionalBranch - Return true if we're currently emitting one branch or the other of a conditio...
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
Address EmitPointerWithAlignment(const Expr *Addr, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitPointerWithAlignment - Given an expression with a pointer type, emit the value and compute our be...
void EmitARCRelease(llvm::Value *value, ARCPreciseLifetime_t precise)
void EmitComplexExprIntoLValue(const Expr *E, LValue dest, bool isInit)
EmitComplexExprIntoLValue - Emit the given expression of complex type and place its result into the s...
RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E, ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke=nullptr)
RValue EmitBuiltinNewDeleteCall(const FunctionProtoType *Type, const CallExpr *TheCallExpr, bool IsDelete)
void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating, AggValueSlot ThisAVS, const CXXConstructExpr *E)
CGDebugInfo * getDebugInfo()
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
void EmitCXXDeleteExpr(const CXXDeleteExpr *E)
const TargetCodeGenInfo & getTargetHooks() const
void EmitAggExpr(const Expr *E, AggValueSlot AS)
EmitAggExpr - Emit the computation of the specified expression of aggregate type.
RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke)
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
ASTContext & getContext() const
CGCallee BuildAppleKextVirtualCall(const CXXMethodDecl *MD, NestedNameSpecifier *Qual, llvm::Type *Ty)
void PopCleanupBlock(bool FallThroughIsBranchThrough=false, bool ForDeactivation=false)
PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest)
RValue EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, const CXXMethodDecl *MD, ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke)
llvm::Type * ConvertType(QualType T)
llvm::Value * EmitCXXTypeidExpr(const CXXTypeidExpr *E)
CodeGenTypes & getTypes() const
void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, LValue LV, QualType Type, SanitizerSet SkippedChecks=SanitizerSet(), llvm::Value *ArraySize=nullptr)
llvm::Value * EmitDynamicCast(Address V, const CXXDynamicCastExpr *DCE)
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
const CallExpr * MustTailCall
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
llvm::Value * EmitCXXNewExpr(const CXXNewExpr *E)
void EmitARCDestroyStrong(Address addr, ARCPreciseLifetime_t precise)
void pushRegularPartialArrayCleanup(llvm::Value *arrayBegin, llvm::Value *arrayEnd, QualType elementType, CharUnits elementAlignment, Destroyer *destroyer)
static bool IsWrappedCXXThis(const Expr *E)
Check if E is a C++ "this" pointer wrapped in value-preserving casts.
void EmitExplicitCastExprType(const ExplicitCastExpr *E, CodeGenFunction *CGF=nullptr)
Emit type info if type of an expression is a variably modified type.
llvm::Module & getModule() const
llvm::Constant * EmitNullConstantForBase(const CXXRecordDecl *Record)
Return a null constant appropriate for zero-initializing a base class with the given type.
llvm::Constant * GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH=false)
Get the address of the RTTI descriptor for the given type.
llvm::Constant * GetAddrOfFunction(GlobalDecl GD, llvm::Type *Ty=nullptr, bool ForVTable=false, bool DontDefer=false, ForDefinition_t IsForDefinition=NotForDefinition)
Return the address of the given function.
llvm::Constant * getAddrOfCXXStructor(GlobalDecl GD, const CGFunctionInfo *FnInfo=nullptr, llvm::FunctionType *FnType=nullptr, bool DontDefer=false, ForDefinition_t IsForDefinition=NotForDefinition)
Return the address of the constructor/destructor of the given type.
const LangOptions & getLangOpts() const
CGCUDARuntime & getCUDARuntime()
Return a reference to the configured CUDA runtime.
CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)
CodeGenTypes & getTypes()
CGCXXABI & getCXXABI() const
const CodeGenOptions & getCodeGenOpts() const
llvm::Function * getIntrinsic(unsigned IID, ArrayRef< llvm::Type * > Tys={})
LangAS GetGlobalVarAddressSpace(const VarDecl *D)
Return the AST address space of the underlying global variable for D, as determined by its declaratio...
llvm::ConstantInt * getSize(CharUnits numChars)
Emit the given number of characters as a value of type size_t.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
const CGFunctionInfo & arrangeCXXMethodDeclaration(const CXXMethodDecl *MD)
C++ methods have some special rules and also have implicit parameters.
CanQualType DeriveThisType(const CXXRecordDecl *RD, const CXXMethodDecl *MD)
Derives the 'this' type for codegen purposes, i.e.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeCXXMethodCall(const CallArgList &args, const FunctionProtoType *type, RequiredArgs required, unsigned numPrefixArgs)
Arrange a call to a C++ method, passing the given arguments.
const CGFunctionInfo & arrangeFreeFunctionCall(const CallArgList &Args, const FunctionType *Ty, bool ChainCall)
Figure out the rules for calling a function with the given formal type using the given arguments.
bool isZeroInitializable(QualType T)
IsZeroInitializable - Return whether a type can be zero-initialized (in the C++ sense) with an LLVM z...
const CGFunctionInfo & arrangeCXXStructorDeclaration(GlobalDecl GD)
llvm::Constant * tryEmitAbstract(const Expr *E, QualType T)
Try to emit the result of the given expression as an abstract constant.
Information for lazily generating a cleanup.
A saved depth on the scope stack.
stable_iterator stable_begin() const
Create a stable reference to the top of the EH stack.
T * pushCleanupWithExtra(CleanupKind Kind, size_t N, As... A)
Push a cleanup with non-constant storage requirements on the stack.
iterator find(stable_iterator save) const
Turn a stable reference to a scope depth into a unstable pointer to the EH stack.
AlignmentSource getAlignmentSource() const
LValue - This represents an lvalue references.
Address getAddress() const
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getAggregate(Address addr, bool isVolatile=false)
Convert an Address to an RValue.
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
A class for recording the number of arguments that a function signature requires.
static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype, unsigned additional)
Compute the arguments required by the given formal prototype, given that there may be some additional...
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
Address performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, Address Addr, LangAS SrcAddr, LangAS DestAddr, llvm::Type *DestTy, bool IsNonNull=false) const
Represents the canonical version of C arrays with a specified constant size.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
Decl - This represents one declaration (or definition), e.g.
The name of a declaration.
QualType getIntegerType() const
Return the integer type this enum decl corresponds to.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
EnumDecl * getDecl() const
QualType getTypeAsWritten() const
getTypeAsWritten - Returns the type that this expression is casting to, as written in the source code...
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
This represents one expression.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const
Determine whether the result of this expression is a temporary object of the given class type.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents a function declaration or definition.
bool isDestroyingOperatorDelete() const
Determine whether this is a destroying operator delete.
QualType getReturnType() const
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
bool isVariadic() const
Whether this function is variadic.
bool isReservedGlobalPlacementOperator() const
Determines whether this operator new or delete is one of the reserved global placement operators: voi...
bool isReplaceableGlobalAllocationFunction(std::optional< unsigned > *AlignmentParam=nullptr, bool *IsNothrow=nullptr) const
Determines whether this function is one of the replaceable global allocation functions: void *operato...
bool isDefaulted() const
Whether this function is defaulted.
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Represents a prototype with parameter type info, e.g.
param_type_iterator param_type_begin() const
unsigned getNumParams() const
QualType getParamType(unsigned i) const
param_type_iterator param_type_end() const
GlobalDecl - represents a global declaration.
CXXCtorType getCtorType() const
const Decl * getDecl() const
Represents an implicitly-generated value initialization of an object of a given type.
Describes an C or C++ initializer list.
bool isStringLiteralInit() const
Is this an initializer for an array of characters, initialized by a string literal or an @encode?
unsigned getNumInits() const
Expr * getArrayFiller()
If this initializer list initializes an array with more elements than there are initializers in the l...
const Expr * getInit(unsigned Init) const
ArrayRef< Expr * > inits()
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
bool hasQualifier() const
Determines whether this member expression actually had a C++ nested-name-specifier prior to the name ...
NestedNameSpecifier * getQualifier() const
If the member name was qualified, retrieves the nested-name-specifier that precedes the member name.
A pointer to member type per C++ 8.3.3 - Pointers to members.
Represents a C++ nested name specifier, such as "\::std::vector::".
ObjCEncodeExpr, used for @encode in Objective-C.
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
LangAS getAddressSpace() const
Return the address space of this type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
QualType getCanonicalType() const
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
bool isPODType(const ASTContext &Context) const
Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
bool hasStrongOrWeakObjCLifetime() const
The collection of all-type qualifiers we support.
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
LangAS getAddressSpace() const
bool mayInsertExtraPadding(bool EmitRemark=false) const
Whether we are allowed to insert extra padding between fields.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
Base for LValueReferenceType and RValueReferenceType.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
SourceLocation getBeginLoc() const LLVM_READONLY
StringLiteral - This represents a string literal expression, e.g.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool isVoidPointerType() const
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
const T * getAs() const
Member-template getAs'.
bool isRecordType() const
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
@ EHCleanup
Denotes a cleanup that should run when a scope is exited using exceptional control flow (a throw stat...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
Matches all kinds of arrays.
bool This(InterpState &S, CodePtr OpPC)
bool Zero(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
CXXCtorType
C++ constructor types.
@ Ctor_Base
Base object ctor.
@ Ctor_Complete
Complete object ctor.
@ Dtor_Complete
Complete object dtor.
LangAS
Defines the address space values used by the address space qualifier of QualType.
const FunctionProtoType * T
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
CharUnits getPointerSize() const
llvm::IntegerType * SizeTy
CharUnits getSizeAlign() const
llvm::PointerType * Int8PtrTy
CharUnits getPointerAlign() const
A metaprogramming class for ensuring that a value will dominate an arbitrary position in a function.
static saved_type save(CodeGenFunction &CGF, type value)
void set(SanitizerMask K, bool Value)
Enable or disable a certain (single) sanitizer.
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.