| OLD | NEW |
| 1 diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h | 1 diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h |
| 2 index bc1bf0b..31fdc74 100644 | 2 index 6ed55ca..16819a4 100644 |
| 3 --- a/include/clang/AST/ExprCXX.h | 3 --- a/include/clang/AST/ExprCXX.h |
| 4 +++ b/include/clang/AST/ExprCXX.h | 4 +++ b/include/clang/AST/ExprCXX.h |
| 5 @@ -1677,6 +1677,9 @@ class CXXNewExpr : public Expr { | 5 @@ -1676,6 +1676,9 @@ class CXXNewExpr : public Expr { |
| 6 /// null. | 6 /// null. |
| 7 FunctionDecl *OperatorDelete; | 7 FunctionDecl *OperatorDelete; |
| 8 | 8 |
| 9 + // TODO(dmikurube): Add a comment. | 9 + // TODO(dmikurube): Add a comment. |
| 10 + FunctionDecl *OperatorNewIntercept; | 10 + FunctionDecl *OperatorNewIntercept; |
| 11 + | 11 + |
| 12 /// \brief The allocated type-source information, as written in the source. | 12 /// \brief The allocated type-source information, as written in the source. |
| 13 TypeSourceInfo *AllocatedTypeInfo; | 13 TypeSourceInfo *AllocatedTypeInfo; |
| 14 | 14 |
| 15 @@ -1753,6 +1756,9 @@ public: | 15 @@ -1752,6 +1755,9 @@ public: |
| 16 FunctionDecl *getOperatorDelete() const { return OperatorDelete; } | 16 FunctionDecl *getOperatorDelete() const { return OperatorDelete; } |
| 17 void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } | 17 void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } |
| 18 | 18 |
| 19 + FunctionDecl *getOperatorNewIntercept() const { return OperatorNewIntercept;
} | 19 + FunctionDecl *getOperatorNewIntercept() const { return OperatorNewIntercept;
} |
| 20 + void setOperatorNewIntercept(FunctionDecl *D) { OperatorNewIntercept = D; } | 20 + void setOperatorNewIntercept(FunctionDecl *D) { OperatorNewIntercept = D; } |
| 21 + | 21 + |
| 22 bool isArray() const { return Array; } | 22 bool isArray() const { return Array; } |
| 23 Expr *getArraySize() { | 23 Expr *getArraySize() { |
| 24 return Array ? cast<Expr>(SubExprs[0]) : 0; | 24 return Array ? cast<Expr>(SubExprs[0]) : 0; |
| 25 @@ -1862,6 +1868,8 @@ public: | 25 @@ -1861,6 +1867,8 @@ public: |
| 26 class CXXDeleteExpr : public Expr { | 26 class CXXDeleteExpr : public Expr { |
| 27 /// Points to the operator delete overload that is used. Could be a member. | 27 /// Points to the operator delete overload that is used. Could be a member. |
| 28 FunctionDecl *OperatorDelete; | 28 FunctionDecl *OperatorDelete; |
| 29 + /// TODO(dmikurube): Add a comment. | 29 + /// TODO(dmikurube): Add a comment. |
| 30 + FunctionDecl *OperatorDeleteIntercept; | 30 + FunctionDecl *OperatorDeleteIntercept; |
| 31 /// The pointer expression to be deleted. | 31 /// The pointer expression to be deleted. |
| 32 Stmt *Argument; | 32 Stmt *Argument; |
| 33 /// Location of the expression. | 33 /// Location of the expression. |
| 34 @@ -1884,7 +1892,9 @@ public: | 34 @@ -1883,7 +1891,9 @@ public: |
| 35 : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false, | 35 : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false, |
| 36 arg->isInstantiationDependent(), | 36 arg->isInstantiationDependent(), |
| 37 arg->containsUnexpandedParameterPack()), | 37 arg->containsUnexpandedParameterPack()), |
| 38 - OperatorDelete(operatorDelete), Argument(arg), Loc(loc), | 38 - OperatorDelete(operatorDelete), Argument(arg), Loc(loc), |
| 39 + OperatorDelete(operatorDelete), | 39 + OperatorDelete(operatorDelete), |
| 40 + OperatorDeleteIntercept(0), | 40 + OperatorDeleteIntercept(0), |
| 41 + Argument(arg), Loc(loc), | 41 + Argument(arg), Loc(loc), |
| 42 GlobalDelete(globalDelete), | 42 GlobalDelete(globalDelete), |
| 43 ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten), | 43 ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten), |
| 44 UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { } | 44 UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { } |
| 45 @@ -1904,6 +1914,12 @@ public: | 45 @@ -1903,6 +1913,12 @@ public: |
| 46 } | 46 } |
| 47 | 47 |
| 48 FunctionDecl *getOperatorDelete() const { return OperatorDelete; } | 48 FunctionDecl *getOperatorDelete() const { return OperatorDelete; } |
| 49 + FunctionDecl *getOperatorDeleteIntercept() const { | 49 + FunctionDecl *getOperatorDeleteIntercept() const { |
| 50 + return OperatorDeleteIntercept; | 50 + return OperatorDeleteIntercept; |
| 51 + } | 51 + } |
| 52 + void setOperatorDeleteIntercept(FunctionDecl *D) { | 52 + void setOperatorDeleteIntercept(FunctionDecl *D) { |
| 53 + OperatorDeleteIntercept = D; | 53 + OperatorDeleteIntercept = D; |
| 54 + } | 54 + } |
| 55 | 55 |
| 56 Expr *getArgument() { return cast<Expr>(Argument); } | 56 Expr *getArgument() { return cast<Expr>(Argument); } |
| 57 const Expr *getArgument() const { return cast<Expr>(Argument); } | 57 const Expr *getArgument() const { return cast<Expr>(Argument); } |
| 58 diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptio
ns.def | 58 diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptio
ns.def |
| 59 index e8fe482..5ac2179 100644 | 59 index 22662e0..5b48593 100644 |
| 60 --- a/include/clang/Basic/LangOptions.def | 60 --- a/include/clang/Basic/LangOptions.def |
| 61 +++ b/include/clang/Basic/LangOptions.def | 61 +++ b/include/clang/Basic/LangOptions.def |
| 62 @@ -132,6 +132,8 @@ BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support") | 62 @@ -137,6 +137,8 @@ BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support") |
| 63 BENIGN_LANGOPT(DebuggerCastResultToId, 1, 0, "for 'po' in the debugger, cast th
e result to id if it is of unknown type") | 63 BENIGN_LANGOPT(DebuggerCastResultToId, 1, 0, "for 'po' in the debugger, cast th
e result to id if it is of unknown type") |
| 64 BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger Objective-C literals and s
ubscripting support") | 64 BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger Objective-C literals and s
ubscripting support") |
| 65 | 65 |
| 66 +BENIGN_LANGOPT(InterceptAllocationFunctions , 1, 0, "intercepting allocation fu
nctions and allocated types") | 66 +BENIGN_LANGOPT(InterceptAllocationFunctions , 1, 0, "intercepting allocation fu
nctions and allocated types") |
| 67 + | 67 + |
| 68 BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking") | 68 BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking") |
| 69 LANGOPT(SinglePrecisionConstants , 1, 0, "treating double-precision floating po
int constants as single precision constants") | 69 LANGOPT(SinglePrecisionConstants , 1, 0, "treating double-precision floating po
int constants as single precision constants") |
| 70 LANGOPT(FastRelaxedMath , 1, 0, "OpenCL fast relaxed math") | 70 LANGOPT(FastRelaxedMath , 1, 0, "OpenCL fast relaxed math") |
| 71 diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td | 71 diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td |
| 72 index 7e7e111..a6da64c 100644 | 72 index efe9818..062b428 100644 |
| 73 --- a/include/clang/Driver/Options.td | 73 --- a/include/clang/Driver/Options.td |
| 74 +++ b/include/clang/Driver/Options.td | 74 +++ b/include/clang/Driver/Options.td |
| 75 @@ -330,6 +330,9 @@ def faddress_sanitizer : Flag<["-"], "faddress-sanitizer">,
Group<f_Group>; | 75 @@ -357,6 +357,9 @@ def fapple_kext : Flag<["-"], "fapple-kext">, Group<f_Group>
, Flags<[CC1Option]> |
| 76 def fno_address_sanitizer : Flag<["-"], "fno-address-sanitizer">, Group<f_Group
>; | 76 HelpText<"Use Apple's kernel extensions ABI">; |
| 77 def fthread_sanitizer : Flag<["-"], "fthread-sanitizer">, Group<f_Group>; | 77 def fapple_pragma_pack : Flag<["-"], "fapple-pragma-pack">, Group<f_Group>, Fla
gs<[CC1Option]>, |
| 78 def fno_thread_sanitizer : Flag<["-"], "fno-thread-sanitizer">, Group<f_Group>; | 78 HelpText<"Enable Apple gcc-compatible #pragma pack handling">; |
| 79 +def fintercept_allocation_functions : Flag<["-"], "fintercept-allocation-functi
ons">, Group<f_Group>, Flags<[CC1Option]>, | 79 +def fintercept_allocation_functions : Flag<["-"], "fintercept-allocation-functi
ons">, Group<f_Group>, Flags<[CC1Option]>, |
| 80 + HelpText<"Intercept allocation functions and allocated types">; | 80 + HelpText<"Intercept allocation functions and allocated types">; |
| 81 +def fno_intercept_allocation_functions : Flag<["-"], "fno-intercept-allocation-
functions">, Group<f_Group>, Flags<[CC1Option]>; | 81 +def fno_intercept_allocation_functions : Flag<["-"], "fno-intercept-allocation-
functions">, Group<f_Group>, Flags<[CC1Option]>; |
| 82 def fasm : Flag<["-"], "fasm">, Group<f_Group>; | 82 def fasm : Flag<["-"], "fasm">, Group<f_Group>; |
| 83 | 83 |
| 84 def fasm_blocks : Flag<["-"], "fasm-blocks">, Group<f_Group>, Flags<[CC1Option]
>; | 84 def fasm_blocks : Flag<["-"], "fasm-blocks">, Group<f_Group>, Flags<[CC1Option]
>; |
| 85 diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h | 85 diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h |
| 86 index 6b4079e..8d75ace 100644 | 86 index 5ce80a6..9a32130 100644 |
| 87 --- a/include/clang/Sema/Sema.h | 87 --- a/include/clang/Sema/Sema.h |
| 88 +++ b/include/clang/Sema/Sema.h | 88 +++ b/include/clang/Sema/Sema.h |
| 89 @@ -3517,6 +3517,9 @@ public: | 89 @@ -3685,6 +3685,9 @@ public: |
| 90 NamespaceDecl *getStdNamespace() const; | 90 NamespaceDecl *getStdNamespace() const; |
| 91 NamespaceDecl *getOrCreateStdNamespace(); | 91 NamespaceDecl *getOrCreateStdNamespace(); |
| 92 | 92 |
| 93 + RecordDecl *getCXXTypeInfoDecl() const; | 93 + RecordDecl *getCXXTypeInfoDecl() const; |
| 94 + RecordDecl *getOrCreateCXXTypeInfoDecl(); | 94 + RecordDecl *getOrCreateCXXTypeInfoDecl(); |
| 95 + | 95 + |
| 96 CXXRecordDecl *getStdBadAlloc() const; | 96 CXXRecordDecl *getStdBadAlloc() const; |
| 97 | 97 |
| 98 /// \brief Tests whether Ty is an instance of std::initializer_list and, if | 98 /// \brief Tests whether Ty is an instance of std::initializer_list and, if |
| 99 @@ -4056,6 +4059,7 @@ public: | 99 @@ -4237,6 +4240,7 @@ public: |
| 100 void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return, | 100 QualType Param1, |
| 101 QualType Argument, | 101 QualType Param2 = QualType(), |
| 102 bool addMallocAttr = false); | 102 bool addMallocAttr = false); |
| 103 + void DeclareGlobalAllocatorInterceptFunctions(DeclarationName Name); | 103 + void DeclareGlobalAllocatorInterceptFunctions(DeclarationName Name); |
| 104 | 104 |
| 105 bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, | 105 bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, |
| 106 DeclarationName Name, FunctionDecl* &Operator, | 106 DeclarationName Name, FunctionDecl* &Operator, |
| 107 diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp | 107 diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp |
| 108 index 55bd199..d0e29a2 100644 | 108 index ee49925..9f5dda9 100644 |
| 109 --- a/lib/AST/ExprCXX.cpp | 109 --- a/lib/AST/ExprCXX.cpp |
| 110 +++ b/lib/AST/ExprCXX.cpp | 110 +++ b/lib/AST/ExprCXX.cpp |
| 111 @@ -92,6 +92,7 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, Function
Decl *operatorNew, | 111 @@ -150,6 +150,7 @@ CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew, |
| 112 ty->isInstantiationDependentType(), | 112 ty->isInstantiationDependentType(), |
| 113 ty->containsUnexpandedParameterPack()), | 113 ty->containsUnexpandedParameterPack()), |
| 114 SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete), | 114 SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete), |
| 115 + OperatorNewIntercept(0), | 115 + OperatorNewIntercept(0), |
| 116 AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens), | 116 AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens), |
| 117 Range(Range), DirectInitRange(directInitRange), | 117 Range(Range), DirectInitRange(directInitRange), |
| 118 GlobalNew(globalNew), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize)
{ | 118 GlobalNew(globalNew), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize)
{ |
| 119 diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp | 119 diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp |
| 120 index 2bb4455..918efa3 100644 | 120 index 071f8b3..2434149 100644 |
| 121 --- a/lib/CodeGen/CGClass.cpp | 121 --- a/lib/CodeGen/CGClass.cpp |
| 122 +++ b/lib/CodeGen/CGClass.cpp | 122 +++ b/lib/CodeGen/CGClass.cpp |
| 123 @@ -1338,7 +1338,8 @@ namespace { | 123 @@ -1364,7 +1364,8 @@ namespace { |
| 124 void Emit(CodeGenFunction &CGF, Flags flags) { | 124 void Emit(CodeGenFunction &CGF, Flags flags) override { |
| 125 const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl); | 125 const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl); |
| 126 const CXXRecordDecl *ClassDecl = Dtor->getParent(); | 126 const CXXRecordDecl *ClassDecl = Dtor->getParent(); |
| 127 - CGF.EmitDeleteCall(Dtor->getOperatorDelete(), CGF.LoadCXXThis(), | 127 - CGF.EmitDeleteCall(Dtor->getOperatorDelete(), CGF.LoadCXXThis(), |
| 128 + // TODO(dmikurube): Not 0 for OperatorDeleteIntercept? | 128 + // TODO(dmikurube): Not 0 for OperatorDeleteIntercept? |
| 129 + CGF.EmitDeleteCall(Dtor->getOperatorDelete(), 0, CGF.LoadCXXThis(), | 129 + CGF.EmitDeleteCall(Dtor->getOperatorDelete(), 0, CGF.LoadCXXThis(), |
| 130 CGF.getContext().getTagDeclType(ClassDecl)); | 130 CGF.getContext().getTagDeclType(ClassDecl)); |
| 131 } | 131 } |
| 132 }; | 132 }; |
| 133 @@ -1361,7 +1362,7 @@ namespace { | 133 @@ -1387,7 +1388,7 @@ namespace { |
| 134 CGF.EmitBlock(callDeleteBB); | 134 CGF.EmitBlock(callDeleteBB); |
| 135 const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl); | 135 const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl); |
| 136 const CXXRecordDecl *ClassDecl = Dtor->getParent(); | 136 const CXXRecordDecl *ClassDecl = Dtor->getParent(); |
| 137 - CGF.EmitDeleteCall(Dtor->getOperatorDelete(), CGF.LoadCXXThis(), | 137 - CGF.EmitDeleteCall(Dtor->getOperatorDelete(), CGF.LoadCXXThis(), |
| 138 + CGF.EmitDeleteCall(Dtor->getOperatorDelete(), 0, CGF.LoadCXXThis(), | 138 + CGF.EmitDeleteCall(Dtor->getOperatorDelete(), 0, CGF.LoadCXXThis(), |
| 139 CGF.getContext().getTagDeclType(ClassDecl)); | 139 CGF.getContext().getTagDeclType(ClassDecl)); |
| 140 CGF.Builder.CreateBr(continueBB); | 140 CGF.Builder.CreateBr(continueBB); |
| 141 | 141 |
| 142 diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp | 142 diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp |
| 143 index 672e86d..983e913 100644 | 143 index f71a3de..6b52585 100644 |
| 144 --- a/lib/CodeGen/CGExprCXX.cpp | 144 --- a/lib/CodeGen/CGExprCXX.cpp |
| 145 +++ b/lib/CodeGen/CGExprCXX.cpp | 145 +++ b/lib/CodeGen/CGExprCXX.cpp |
| 146 @@ -1233,6 +1233,31 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNew
Expr *E) { | 146 @@ -1186,6 +1186,31 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNew
Expr *E) { |
| 147 allocatorArgs, allocator); | 147 RV = EmitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs); |
| 148 } | 148 } |
| 149 | 149 |
| 150 + FunctionDecl *Intercept = E->getOperatorNewIntercept(); | 150 + FunctionDecl *Intercept = E->getOperatorNewIntercept(); |
| 151 + if (getContext().getLangOpts().InterceptAllocationFunctions && | 151 + if (getContext().getLangOpts().InterceptAllocationFunctions && |
| 152 + getContext().getLangOpts().RTTI && | 152 + getContext().getLangOpts().RTTI && |
| 153 + Intercept) { | 153 + Intercept) { |
| 154 + const FunctionProtoType *InterceptType = | 154 + const FunctionProtoType *InterceptType = |
| 155 + Intercept->getType()->castAs<FunctionProtoType>(); | 155 + Intercept->getType()->castAs<FunctionProtoType>(); |
| 156 + | 156 + |
| 157 + QualType ThirdType = InterceptType->getArgType(2); | 157 + QualType ThirdType = InterceptType->getParamType(2); |
| 158 + const IdentifierInfo *identifier = ThirdType.getBaseTypeIdentifier(); | 158 + const IdentifierInfo *identifier = ThirdType.getBaseTypeIdentifier(); |
| 159 + if (identifier && strcmp(identifier->getNameStart(), "type_info") == 0) { | 159 + if (identifier && strcmp(identifier->getNameStart(), "type_info") == 0) { |
| 160 + llvm::Value* TypeInfo = Builder.CreateBitCast( | 160 + llvm::Value* TypeInfo = Builder.CreateBitCast( |
| 161 + CGM.GetAddrOfRTTIDescriptor(allocType.getUnqualifiedType()), | 161 + CGM.GetAddrOfRTTIDescriptor(allocType.getUnqualifiedType()), |
| 162 + ConvertType(ThirdType)); | 162 + ConvertType(ThirdType)); |
| 163 + | 163 + |
| 164 + CallArgList InterceptArgs; | 164 + CallArgList InterceptArgs; |
| 165 + InterceptArgs.add(RV, getContext().VoidPtrTy); | 165 + InterceptArgs.add(RV, getContext().VoidPtrTy); |
| 166 + InterceptArgs.add(RValue::get(allocSize), sizeType); | 166 + InterceptArgs.add(RValue::get(allocSize), sizeType); |
| 167 + InterceptArgs.add(RValue::get(TypeInfo), ThirdType); | 167 + InterceptArgs.add(RValue::get(TypeInfo), ThirdType); |
| 168 + RV = EmitCall(CGM.getTypes().arrangeFreeFunctionCall(InterceptArgs, | 168 + RV = EmitCall(CGM.getTypes().arrangeFreeFunctionCall(InterceptArgs, |
| 169 + InterceptType), | 169 + InterceptType), |
| 170 + CGM.GetAddrOfFunction(Intercept), ReturnValueSlot(), | 170 + CGM.GetAddrOfFunction(Intercept), ReturnValueSlot(), |
| 171 + InterceptArgs, Intercept); | 171 + InterceptArgs, Intercept); |
| 172 + } | 172 + } |
| 173 + } | 173 + } |
| 174 + | 174 + |
| 175 // Emit a null check on the allocation result if the allocation | 175 // Emit a null check on the allocation result if the allocation |
| 176 // function is allowed to return null (because it has a non-throwing | 176 // function is allowed to return null (because it has a non-throwing |
| 177 // exception spec; for this part, we inline | 177 // exception spec; for this part, we inline |
| 178 @@ -1323,6 +1348,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewE
xpr *E) { | 178 @@ -1276,6 +1301,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewE
xpr *E) { |
| 179 } | 179 } |
| 180 | 180 |
| 181 void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD, | 181 void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD, |
| 182 + const FunctionDecl *DeleteFDIntercept, | 182 + const FunctionDecl *DeleteFDIntercept, |
| 183 llvm::Value *Ptr, | 183 llvm::Value *Ptr, |
| 184 QualType DeleteTy) { | 184 QualType DeleteTy) { |
| 185 assert(DeleteFD->getOverloadedOperator() == OO_Delete); | 185 assert(DeleteFD->getOverloadedOperator() == OO_Delete); |
| 186 @@ -1344,7 +1370,39 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *
DeleteFD, | 186 @@ -1297,7 +1323,39 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *
DeleteFD, |
| 187 | 187 |
| 188 QualType ArgTy = DeleteFTy->getArgType(0); | 188 QualType ArgTy = DeleteFTy->getParamType(0); |
| 189 llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy)); | 189 llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy)); |
| 190 - DeleteArgs.add(RValue::get(DeletePtr), ArgTy); | 190 - DeleteArgs.add(RValue::get(DeletePtr), ArgTy); |
| 191 + | 191 + |
| 192 + RValue RV = RValue::get(DeletePtr); | 192 + RValue RV = RValue::get(DeletePtr); |
| 193 + const FunctionDecl *Intercept = DeleteFDIntercept; | 193 + const FunctionDecl *Intercept = DeleteFDIntercept; |
| 194 + if (getContext().getLangOpts().InterceptAllocationFunctions && | 194 + if (getContext().getLangOpts().InterceptAllocationFunctions && |
| 195 + getContext().getLangOpts().RTTI && | 195 + getContext().getLangOpts().RTTI && |
| 196 + Intercept) { | 196 + Intercept) { |
| 197 + const FunctionProtoType *InterceptType = | 197 + const FunctionProtoType *InterceptType = |
| 198 + Intercept->getType()->castAs<FunctionProtoType>(); | 198 + Intercept->getType()->castAs<FunctionProtoType>(); |
| 199 + | 199 + |
| 200 + llvm::Value *SizeIntercept = 0; | 200 + llvm::Value *SizeIntercept = 0; |
| 201 + QualType SecondType = InterceptType->getArgType(1); | 201 + QualType SecondType = InterceptType->getParamType(1); |
| 202 + CharUnits DeleteTypeSize = getContext().getTypeSizeInChars(DeleteTy); | 202 + CharUnits DeleteTypeSize = getContext().getTypeSizeInChars(DeleteTy); |
| 203 + SizeIntercept = llvm::ConstantInt::get(ConvertType(SecondType), | 203 + SizeIntercept = llvm::ConstantInt::get(ConvertType(SecondType), |
| 204 + DeleteTypeSize.getQuantity()); | 204 + DeleteTypeSize.getQuantity()); |
| 205 + | 205 + |
| 206 + QualType ThirdType = InterceptType->getArgType(2); | 206 + QualType ThirdType = InterceptType->getParamType(2); |
| 207 + const IdentifierInfo *identifier = ThirdType.getBaseTypeIdentifier(); | 207 + const IdentifierInfo *identifier = ThirdType.getBaseTypeIdentifier(); |
| 208 + if (identifier && strcmp(identifier->getNameStart(), "type_info") == 0) { | 208 + if (identifier && strcmp(identifier->getNameStart(), "type_info") == 0) { |
| 209 + llvm::Value* TypeInfo = Builder.CreateBitCast( | 209 + llvm::Value* TypeInfo = Builder.CreateBitCast( |
| 210 + CGM.GetAddrOfRTTIDescriptor(DeleteTy.getUnqualifiedType()), | 210 + CGM.GetAddrOfRTTIDescriptor(DeleteTy.getUnqualifiedType()), |
| 211 + ConvertType(ThirdType)); | 211 + ConvertType(ThirdType)); |
| 212 + | 212 + |
| 213 + CallArgList InterceptArgs; | 213 + CallArgList InterceptArgs; |
| 214 + InterceptArgs.add(RValue::get(DeletePtr), getContext().VoidPtrTy); | 214 + InterceptArgs.add(RValue::get(DeletePtr), getContext().VoidPtrTy); |
| 215 + InterceptArgs.add(RValue::get(SizeIntercept), SecondType); | 215 + InterceptArgs.add(RValue::get(SizeIntercept), SecondType); |
| 216 + InterceptArgs.add(RValue::get(TypeInfo), ThirdType); | 216 + InterceptArgs.add(RValue::get(TypeInfo), ThirdType); |
| 217 + RV = EmitCall(CGM.getTypes().arrangeFreeFunctionCall(InterceptArgs, | 217 + RV = EmitCall(CGM.getTypes().arrangeFreeFunctionCall(InterceptArgs, |
| 218 + InterceptType), | 218 + InterceptType), |
| 219 + CGM.GetAddrOfFunction(Intercept), ReturnValueSlot(), | 219 + CGM.GetAddrOfFunction(Intercept), ReturnValueSlot(), |
| 220 + InterceptArgs, Intercept); | 220 + InterceptArgs, Intercept); |
| 221 + } | 221 + } |
| 222 + } | 222 + } |
| 223 + DeleteArgs.add(RV, ArgTy); | 223 + DeleteArgs.add(RV, ArgTy); |
| 224 | 224 |
| 225 if (Size) | 225 if (Size) |
| 226 DeleteArgs.add(RValue::get(Size), SizeTy); | 226 DeleteArgs.add(RValue::get(Size), SizeTy); |
| 227 @@ -1360,15 +1418,20 @@ namespace { | 227 @@ -1311,15 +1369,20 @@ namespace { |
| 228 struct CallObjectDelete : EHScopeStack::Cleanup { | 228 struct CallObjectDelete : EHScopeStack::Cleanup { |
| 229 llvm::Value *Ptr; | 229 llvm::Value *Ptr; |
| 230 const FunctionDecl *OperatorDelete; | 230 const FunctionDecl *OperatorDelete; |
| 231 + const FunctionDecl *OperatorDeleteIntercept; | 231 + const FunctionDecl *OperatorDeleteIntercept; |
| 232 QualType ElementType; | 232 QualType ElementType; |
| 233 | 233 |
| 234 CallObjectDelete(llvm::Value *Ptr, | 234 CallObjectDelete(llvm::Value *Ptr, |
| 235 const FunctionDecl *OperatorDelete, | 235 const FunctionDecl *OperatorDelete, |
| 236 + const FunctionDecl *OperatorDeleteIntercept, | 236 + const FunctionDecl *OperatorDeleteIntercept, |
| 237 QualType ElementType) | 237 QualType ElementType) |
| 238 - : Ptr(Ptr), OperatorDelete(OperatorDelete), ElementType(ElementType) {} | 238 - : Ptr(Ptr), OperatorDelete(OperatorDelete), ElementType(ElementType) {} |
| 239 + : Ptr(Ptr), OperatorDelete(OperatorDelete), | 239 + : Ptr(Ptr), OperatorDelete(OperatorDelete), |
| 240 + OperatorDeleteIntercept(OperatorDeleteIntercept), | 240 + OperatorDeleteIntercept(OperatorDeleteIntercept), |
| 241 + ElementType(ElementType) {} | 241 + ElementType(ElementType) {} |
| 242 | 242 |
| 243 void Emit(CodeGenFunction &CGF, Flags flags) { | 243 void Emit(CodeGenFunction &CGF, Flags flags) override { |
| 244 - CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType); | 244 - CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType); |
| 245 + CGF.EmitDeleteCall(OperatorDelete, OperatorDeleteIntercept, Ptr, | 245 + CGF.EmitDeleteCall(OperatorDelete, OperatorDeleteIntercept, Ptr, |
| 246 + ElementType); | 246 + ElementType); |
| 247 } | 247 } |
| 248 }; | 248 }; |
| 249 } | 249 } |
| 250 @@ -1376,6 +1439,7 @@ namespace { | 250 @@ -1327,6 +1390,7 @@ namespace { |
| 251 /// Emit the code for deleting a single object. | 251 /// Emit the code for deleting a single object. |
| 252 static void EmitObjectDelete(CodeGenFunction &CGF, | 252 static void EmitObjectDelete(CodeGenFunction &CGF, |
| 253 const FunctionDecl *OperatorDelete, | 253 const FunctionDecl *OperatorDelete, |
| 254 + const FunctionDecl *OperatorDeleteIntercept, | 254 + const FunctionDecl *OperatorDeleteIntercept, |
| 255 llvm::Value *Ptr, | 255 llvm::Value *Ptr, |
| 256 QualType ElementType, | 256 QualType ElementType, |
| 257 bool UseGlobalDelete) { | 257 bool UseGlobalDelete) { |
| 258 @@ -1399,6 +1463,7 @@ static void EmitObjectDelete(CodeGenFunction &CGF, | 258 @@ -1350,6 +1414,7 @@ static void EmitObjectDelete(CodeGenFunction &CGF, |
| 259 | 259 |
| 260 CGF.EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup, | 260 CGF.EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup, |
| 261 completePtr, OperatorDelete
, | 261 completePtr, OperatorDelete
, |
| 262 + OperatorDeleteIntercept, | 262 + OperatorDeleteIntercept, |
| 263 ElementType); | 263 ElementType); |
| 264 } | 264 } |
| 265 | 265 |
| 266 @@ -1420,7 +1485,9 @@ static void EmitObjectDelete(CodeGenFunction &CGF, | 266 @@ -1371,7 +1436,9 @@ static void EmitObjectDelete(CodeGenFunction &CGF, |
| 267 // This doesn't have to a conditional cleanup because we're going | 267 // This doesn't have to a conditional cleanup because we're going |
| 268 // to pop it off in a second. | 268 // to pop it off in a second. |
| 269 CGF.EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup, | 269 CGF.EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup, |
| 270 - Ptr, OperatorDelete, ElementType); | 270 - Ptr, OperatorDelete, ElementType); |
| 271 + Ptr, OperatorDelete, | 271 + Ptr, OperatorDelete, |
| 272 + OperatorDeleteIntercept, | 272 + OperatorDeleteIntercept, |
| 273 + ElementType); | 273 + ElementType); |
| 274 | 274 |
| 275 if (Dtor) | 275 if (Dtor) |
| 276 CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, | 276 CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, |
| 277 @@ -1458,16 +1525,20 @@ namespace { | 277 @@ -1409,16 +1476,20 @@ namespace { |
| 278 struct CallArrayDelete : EHScopeStack::Cleanup { | 278 struct CallArrayDelete : EHScopeStack::Cleanup { |
| 279 llvm::Value *Ptr; | 279 llvm::Value *Ptr; |
| 280 const FunctionDecl *OperatorDelete; | 280 const FunctionDecl *OperatorDelete; |
| 281 + const FunctionDecl *OperatorDeleteIntercept; | 281 + const FunctionDecl *OperatorDeleteIntercept; |
| 282 llvm::Value *NumElements; | 282 llvm::Value *NumElements; |
| 283 QualType ElementType; | 283 QualType ElementType; |
| 284 CharUnits CookieSize; | 284 CharUnits CookieSize; |
| 285 | 285 |
| 286 CallArrayDelete(llvm::Value *Ptr, | 286 CallArrayDelete(llvm::Value *Ptr, |
| 287 const FunctionDecl *OperatorDelete, | 287 const FunctionDecl *OperatorDelete, |
| 288 + const FunctionDecl *OperatorDeleteIntercept, | 288 + const FunctionDecl *OperatorDeleteIntercept, |
| 289 llvm::Value *NumElements, | 289 llvm::Value *NumElements, |
| 290 QualType ElementType, | 290 QualType ElementType, |
| 291 CharUnits CookieSize) | 291 CharUnits CookieSize) |
| 292 - : Ptr(Ptr), OperatorDelete(OperatorDelete), NumElements(NumElements), | 292 - : Ptr(Ptr), OperatorDelete(OperatorDelete), NumElements(NumElements), |
| 293 + : Ptr(Ptr), OperatorDelete(OperatorDelete), | 293 + : Ptr(Ptr), OperatorDelete(OperatorDelete), |
| 294 + OperatorDeleteIntercept(OperatorDeleteIntercept), | 294 + OperatorDeleteIntercept(OperatorDeleteIntercept), |
| 295 + NumElements(NumElements), | 295 + NumElements(NumElements), |
| 296 ElementType(ElementType), CookieSize(CookieSize) {} | 296 ElementType(ElementType), CookieSize(CookieSize) {} |
| 297 | 297 |
| 298 void Emit(CodeGenFunction &CGF, Flags flags) { | 298 void Emit(CodeGenFunction &CGF, Flags flags) override { |
| 299 @@ -1481,7 +1552,42 @@ namespace { | 299 @@ -1432,7 +1503,42 @@ namespace { |
| 300 QualType VoidPtrTy = DeleteFTy->getArgType(0); | 300 QualType VoidPtrTy = DeleteFTy->getParamType(0); |
| 301 llvm::Value *DeletePtr | 301 llvm::Value *DeletePtr |
| 302 = CGF.Builder.CreateBitCast(Ptr, CGF.ConvertType(VoidPtrTy)); | 302 = CGF.Builder.CreateBitCast(Ptr, CGF.ConvertType(VoidPtrTy)); |
| 303 - Args.add(RValue::get(DeletePtr), VoidPtrTy); | 303 - Args.add(RValue::get(DeletePtr), VoidPtrTy); |
| 304 + | 304 + |
| 305 + RValue RV = RValue::get(DeletePtr); | 305 + RValue RV = RValue::get(DeletePtr); |
| 306 + const FunctionDecl *Intercept = OperatorDeleteIntercept; | 306 + const FunctionDecl *Intercept = OperatorDeleteIntercept; |
| 307 + if (CGF.CGM.getContext().getLangOpts().InterceptAllocationFunctions && | 307 + if (CGF.CGM.getContext().getLangOpts().InterceptAllocationFunctions && |
| 308 + CGF.CGM.getContext().getLangOpts().RTTI && | 308 + CGF.CGM.getContext().getLangOpts().RTTI && |
| 309 + Intercept) { | 309 + Intercept) { |
| 310 + const FunctionProtoType *InterceptType = | 310 + const FunctionProtoType *InterceptType = |
| 311 + Intercept->getType()->castAs<FunctionProtoType>(); | 311 + Intercept->getType()->castAs<FunctionProtoType>(); |
| 312 + | 312 + |
| 313 + llvm::Value *SizeIntercept = 0; | 313 + llvm::Value *SizeIntercept = 0; |
| 314 + QualType SecondType = InterceptType->getArgType(1); | 314 + QualType SecondType = InterceptType->getParamType(1); |
| 315 + CharUnits DeleteTypeSize = | 315 + CharUnits DeleteTypeSize = |
| 316 + CGF.CGM.getContext().getTypeSizeInChars(ElementType); | 316 + CGF.CGM.getContext().getTypeSizeInChars(ElementType); |
| 317 + SizeIntercept = llvm::ConstantInt::get(CGF.ConvertType(SecondType), | 317 + SizeIntercept = llvm::ConstantInt::get(CGF.ConvertType(SecondType), |
| 318 + DeleteTypeSize.getQuantity()); | 318 + DeleteTypeSize.getQuantity()); |
| 319 + | 319 + |
| 320 + QualType ThirdType = InterceptType->getArgType(2); | 320 + QualType ThirdType = InterceptType->getParamType(2); |
| 321 + const IdentifierInfo *identifier = ThirdType.getBaseTypeIdentifier(); | 321 + const IdentifierInfo *identifier = ThirdType.getBaseTypeIdentifier(); |
| 322 + if (identifier && strcmp(identifier->getNameStart(), "type_info") == 0)
{ | 322 + if (identifier && strcmp(identifier->getNameStart(), "type_info") == 0)
{ |
| 323 + llvm::Value* TypeInfo = CGF.Builder.CreateBitCast( | 323 + llvm::Value* TypeInfo = CGF.Builder.CreateBitCast( |
| 324 + CGF.CGM.GetAddrOfRTTIDescriptor(ElementType.getUnqualifiedType()), | 324 + CGF.CGM.GetAddrOfRTTIDescriptor(ElementType.getUnqualifiedType()), |
| 325 + CGF.ConvertType(ThirdType)); | 325 + CGF.ConvertType(ThirdType)); |
| 326 + | 326 + |
| 327 + CallArgList InterceptArgs; | 327 + CallArgList InterceptArgs; |
| 328 + InterceptArgs.add(RValue::get(DeletePtr), | 328 + InterceptArgs.add(RValue::get(DeletePtr), |
| 329 + CGF.CGM.getContext().VoidPtrTy); | 329 + CGF.CGM.getContext().VoidPtrTy); |
| 330 + InterceptArgs.add(RValue::get(SizeIntercept), SecondType); | 330 + InterceptArgs.add(RValue::get(SizeIntercept), SecondType); |
| 331 + InterceptArgs.add(RValue::get(TypeInfo), ThirdType); | 331 + InterceptArgs.add(RValue::get(TypeInfo), ThirdType); |
| 332 + RV = CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall( | 332 + RV = CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall( |
| 333 + InterceptArgs, InterceptType), | 333 + InterceptArgs, InterceptType), |
| 334 + CGF.CGM.GetAddrOfFunction(Intercept), | 334 + CGF.CGM.GetAddrOfFunction(Intercept), |
| 335 + ReturnValueSlot(), | 335 + ReturnValueSlot(), |
| 336 + InterceptArgs, Intercept); | 336 + InterceptArgs, Intercept); |
| 337 + } | 337 + } |
| 338 + } | 338 + } |
| 339 + Args.add(RV, VoidPtrTy); | 339 + Args.add(RV, VoidPtrTy); |
| 340 | 340 |
| 341 // Pass the original requested size as the second argument. | 341 // Pass the original requested size as the second argument. |
| 342 if (DeleteFTy->getNumArgs() == 2) { | 342 if (DeleteFTy->getNumParams() == 2) { |
| 343 @@ -1530,8 +1636,10 @@ static void EmitArrayDelete(CodeGenFunction &CGF, | 343 @@ -1479,8 +1585,10 @@ static void EmitArrayDelete(CodeGenFunction &CGF, |
| 344 | 344 |
| 345 // Make sure that we call delete even if one of the dtors throws. | 345 // Make sure that we call delete even if one of the dtors throws. |
| 346 const FunctionDecl *operatorDelete = E->getOperatorDelete(); | 346 const FunctionDecl *operatorDelete = E->getOperatorDelete(); |
| 347 + const FunctionDecl *operatorDeleteIntercept = E->getOperatorDeleteIntercept()
; | 347 + const FunctionDecl *operatorDeleteIntercept = E->getOperatorDeleteIntercept()
; |
| 348 CGF.EHStack.pushCleanup<CallArrayDelete>(NormalAndEHCleanup, | 348 CGF.EHStack.pushCleanup<CallArrayDelete>(NormalAndEHCleanup, |
| 349 allocatedPtr, operatorDelete, | 349 allocatedPtr, operatorDelete, |
| 350 + operatorDeleteIntercept, | 350 + operatorDeleteIntercept, |
| 351 numElements, elementType, | 351 numElements, elementType, |
| 352 cookieSize); | 352 cookieSize); |
| 353 | 353 |
| 354 @@ -1597,7 +1705,8 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExp
r *E) { | 354 @@ -1546,7 +1654,8 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExp
r *E) { |
| 355 if (E->isArrayForm()) { | 355 if (E->isArrayForm()) { |
| 356 EmitArrayDelete(*this, E, Ptr, DeleteTy); | 356 EmitArrayDelete(*this, E, Ptr, DeleteTy); |
| 357 } else { | 357 } else { |
| 358 - EmitObjectDelete(*this, E->getOperatorDelete(), Ptr, DeleteTy, | 358 - EmitObjectDelete(*this, E->getOperatorDelete(), Ptr, DeleteTy, |
| 359 + EmitObjectDelete(*this, E->getOperatorDelete(), | 359 + EmitObjectDelete(*this, E->getOperatorDelete(), |
| 360 + E->getOperatorDeleteIntercept(), Ptr, DeleteTy, | 360 + E->getOperatorDeleteIntercept(), Ptr, DeleteTy, |
| 361 E->isGlobalDelete()); | 361 E->isGlobalDelete()); |
| 362 } | 362 } |
| 363 | 363 |
| 364 diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h | 364 diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h |
| 365 index 1b62048..f9241cc 100644 | 365 index c583a30..dbf3717 100644 |
| 366 --- a/lib/CodeGen/CodeGenFunction.h | 366 --- a/lib/CodeGen/CodeGenFunction.h |
| 367 +++ b/lib/CodeGen/CodeGenFunction.h | 367 +++ b/lib/CodeGen/CodeGenFunction.h |
| 368 @@ -1620,8 +1620,9 @@ public: | 368 @@ -1641,8 +1641,9 @@ public: |
| 369 llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E); | 369 llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E); |
| 370 void EmitCXXDeleteExpr(const CXXDeleteExpr *E); | 370 void EmitCXXDeleteExpr(const CXXDeleteExpr *E); |
| 371 | 371 |
| 372 - void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr, | 372 - void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr, |
| 373 - QualType DeleteTy); | 373 - QualType DeleteTy); |
| 374 + void EmitDeleteCall(const FunctionDecl *DeleteFD, | 374 + void EmitDeleteCall(const FunctionDecl *DeleteFD, |
| 375 + const FunctionDecl *DeleteFDIntercept, | 375 + const FunctionDecl *DeleteFDIntercept, |
| 376 + llvm::Value *Ptr, QualType DeleteTy); | 376 + llvm::Value *Ptr, QualType DeleteTy); |
| 377 | 377 |
| 378 llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E); | 378 llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E); |
| 379 llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE); | 379 llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE); |
| 380 diff --git a/lib/CodeGen/EHScopeStack.h b/lib/CodeGen/EHScopeStack.h | 380 diff --git a/lib/CodeGen/EHScopeStack.h b/lib/CodeGen/EHScopeStack.h |
| 381 index e9d9a33..7adf8c8 100644 | 381 index 166d420..5f79adf 100644 |
| 382 --- a/lib/CodeGen/EHScopeStack.h | 382 --- a/lib/CodeGen/EHScopeStack.h |
| 383 +++ b/lib/CodeGen/EHScopeStack.h | 383 +++ b/lib/CodeGen/EHScopeStack.h |
| 384 @@ -356,6 +356,14 @@ public: | 384 @@ -356,6 +356,14 @@ public: |
| 385 (void) Obj; | 385 (void) Obj; |
| 386 } | 386 } |
| 387 | 387 |
| 388 + /// Push a lazily-created cleanup on the stack. | 388 + /// Push a lazily-created cleanup on the stack. |
| 389 + template <class T, class A0, class A1, class A2, class A3, class A4, class A5
> | 389 + template <class T, class A0, class A1, class A2, class A3, class A4, class A5
> |
| 390 + void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
{ | 390 + void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
{ |
| 391 + void *Buffer = pushCleanup(Kind, sizeof(T)); | 391 + void *Buffer = pushCleanup(Kind, sizeof(T)); |
| 392 + Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3, a4, a5); | 392 + Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3, a4, a5); |
| 393 + (void) Obj; | 393 + (void) Obj; |
| 394 + } | 394 + } |
| 395 + | 395 + |
| 396 // Feel free to add more variants of the following: | 396 // Feel free to add more variants of the following: |
| 397 | 397 |
| 398 /// Push a cleanup with non-constant storage requirements on the | 398 /// Push a cleanup with non-constant storage requirements on the |
| 399 diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp | 399 diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp |
| 400 index d19486e..e4cb913 100644 | 400 index ea60551..35a06a3 100644 |
| 401 --- a/lib/Driver/Tools.cpp | 401 --- a/lib/Driver/Tools.cpp |
| 402 +++ b/lib/Driver/Tools.cpp | 402 +++ b/lib/Driver/Tools.cpp |
| 403 @@ -2887,6 +2887,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction
&JA, | 403 @@ -3144,6 +3144,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction
&JA, |
| 404 if (getToolChain().SupportsProfiling()) | 404 if (getToolChain().SupportsProfiling()) |
| 405 Args.AddLastArg(CmdArgs, options::OPT_pg); | 405 Args.AddLastArg(CmdArgs, options::OPT_pg); |
| 406 | 406 |
| 407 + if (Args.hasFlag(options::OPT_fintercept_allocation_functions, | 407 + if (Args.hasFlag(options::OPT_fintercept_allocation_functions, |
| 408 + options::OPT_fno_intercept_allocation_functions, false)) { | 408 + options::OPT_fno_intercept_allocation_functions, false)) { |
| 409 + CmdArgs.push_back("-fintercept-allocation-functions"); | 409 + CmdArgs.push_back("-fintercept-allocation-functions"); |
| 410 + CmdArgs.push_back("-include"); | 410 + CmdArgs.push_back("-include"); |
| 411 + CmdArgs.push_back("typeinfo"); | 411 + CmdArgs.push_back("typeinfo"); |
| 412 + } | 412 + } |
| 413 + | 413 + |
| 414 // -flax-vector-conversions is default. | 414 // -flax-vector-conversions is default. |
| 415 if (!Args.hasFlag(options::OPT_flax_vector_conversions, | 415 if (!Args.hasFlag(options::OPT_flax_vector_conversions, |
| 416 options::OPT_fno_lax_vector_conversions)) | 416 options::OPT_fno_lax_vector_conversions)) |
| 417 diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocati
on.cpp | 417 diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocati
on.cpp |
| 418 index 97ca50a..8a45713 100644 | 418 index d744865..2efac8e 100644 |
| 419 --- a/lib/Frontend/CompilerInvocation.cpp | 419 --- a/lib/Frontend/CompilerInvocation.cpp |
| 420 +++ b/lib/Frontend/CompilerInvocation.cpp | 420 +++ b/lib/Frontend/CompilerInvocation.cpp |
| 421 @@ -1314,6 +1314,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args
, InputKind IK, | 421 @@ -1395,6 +1395,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args
, InputKind IK, |
| 422 Opts.DebuggerSupport = Args.hasArg(OPT_fdebugger_support); | 422 Opts.DebuggerSupport = Args.hasArg(OPT_fdebugger_support); |
| 423 Opts.DebuggerCastResultToId = Args.hasArg(OPT_fdebugger_cast_result_to_id); | 423 Opts.DebuggerCastResultToId = Args.hasArg(OPT_fdebugger_cast_result_to_id); |
| 424 Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal); | 424 Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal); |
| 425 + Opts.InterceptAllocationFunctions = | 425 + Opts.InterceptAllocationFunctions = |
| 426 + Args.hasArg(OPT_fintercept_allocation_functions); | 426 + Args.hasArg(OPT_fintercept_allocation_functions); |
| 427 Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack); | 427 Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack); |
| 428 Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name); | 428 Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name); |
| 429 | 429 |
| 430 diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp | 430 diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp |
| 431 index 0b79953..eb1ae84 100644 | 431 index 1a5a4ed..a1dfbf1 100644 |
| 432 --- a/lib/Sema/SemaDeclCXX.cpp | 432 --- a/lib/Sema/SemaDeclCXX.cpp |
| 433 +++ b/lib/Sema/SemaDeclCXX.cpp | 433 +++ b/lib/Sema/SemaDeclCXX.cpp |
| 434 @@ -5934,6 +5934,7 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor)
{ | 434 @@ -6222,6 +6222,7 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor)
{ |
| 435 | 435 |
| 436 MarkFunctionReferenced(Loc, OperatorDelete); | 436 MarkFunctionReferenced(Loc, OperatorDelete); |
| 437 | 437 |
| 438 + // TODO(dmikurube): OperatorDeleteIntercept required? | 438 + // TODO(dmikurube): OperatorDeleteIntercept required? |
| 439 Destructor->setOperatorDelete(OperatorDelete); | 439 Destructor->setOperatorDelete(OperatorDelete); |
| 440 } | 440 } |
| 441 | 441 |
| 442 @@ -6438,6 +6439,32 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() { | 442 @@ -6724,6 +6725,32 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() { |
| 443 return getStdNamespace(); | 443 return getStdNamespace(); |
| 444 } | 444 } |
| 445 | 445 |
| 446 +RecordDecl *Sema::getCXXTypeInfoDecl() const { | 446 +RecordDecl *Sema::getCXXTypeInfoDecl() const { |
| 447 + return CXXTypeInfoDecl; | 447 + return CXXTypeInfoDecl; |
| 448 +} | 448 +} |
| 449 + | 449 + |
| 450 +RecordDecl *Sema::getOrCreateCXXTypeInfoDecl() { | 450 +RecordDecl *Sema::getOrCreateCXXTypeInfoDecl() { |
| 451 + if (!CXXTypeInfoDecl) { | 451 + if (!CXXTypeInfoDecl) { |
| 452 + IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info"); | 452 + IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info"); |
| 453 + LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName); | 453 + LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName); |
| 454 + NamespaceDecl* StdNamespace = getStdNamespace(); | 454 + NamespaceDecl* StdNamespace = getStdNamespace(); |
| 455 + if (!StdNamespace) | 455 + if (!StdNamespace) |
| 456 + return NULL; | 456 + return NULL; |
| 457 + LookupQualifiedName(R, StdNamespace); | 457 + LookupQualifiedName(R, StdNamespace); |
| 458 + CXXTypeInfoDecl = R.getAsSingle<RecordDecl>(); | 458 + CXXTypeInfoDecl = R.getAsSingle<RecordDecl>(); |
| 459 + // Microsoft's typeinfo doesn't have type_info in std but in the global | 459 + // Microsoft's typeinfo doesn't have type_info in std but in the global |
| 460 + // namespace if _HAS_EXCEPTIONS is defined to 0. See PR13153. | 460 + // namespace if _HAS_EXCEPTIONS is defined to 0. See PR13153. |
| 461 + if (!CXXTypeInfoDecl && LangOpts.MicrosoftMode) { | 461 + if (!CXXTypeInfoDecl && LangOpts.MSVCCompat) { |
| 462 + LookupQualifiedName(R, Context.getTranslationUnitDecl()); | 462 + LookupQualifiedName(R, Context.getTranslationUnitDecl()); |
| 463 + CXXTypeInfoDecl = R.getAsSingle<RecordDecl>(); | 463 + CXXTypeInfoDecl = R.getAsSingle<RecordDecl>(); |
| 464 + } | 464 + } |
| 465 + if (!CXXTypeInfoDecl) | 465 + if (!CXXTypeInfoDecl) |
| 466 + return NULL; | 466 + return NULL; |
| 467 + } | 467 + } |
| 468 + | 468 + |
| 469 + return getCXXTypeInfoDecl(); | 469 + return getCXXTypeInfoDecl(); |
| 470 +} | 470 +} |
| 471 + | 471 + |
| 472 bool Sema::isStdInitializerList(QualType Ty, QualType *Element) { | 472 bool Sema::isStdInitializerList(QualType Ty, QualType *Element) { |
| 473 assert(getLangOpts().CPlusPlus && | 473 assert(getLangOpts().CPlusPlus && |
| 474 "Looking for std::initializer_list outside of C++."); | 474 "Looking for std::initializer_list outside of C++."); |
| 475 diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp | 475 diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp |
| 476 index 39c4211..b7efc6b 100644 | 476 index 8b9c0e2..305c886 100644 |
| 477 --- a/lib/Sema/SemaExprCXX.cpp | 477 --- a/lib/Sema/SemaExprCXX.cpp |
| 478 +++ b/lib/Sema/SemaExprCXX.cpp | 478 +++ b/lib/Sema/SemaExprCXX.cpp |
| 479 @@ -417,26 +417,15 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation
LParenLoc, | 479 @@ -454,26 +454,15 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation
LParenLoc, |
| 480 if (!getStdNamespace()) | 480 if (!getStdNamespace()) |
| 481 return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); | 481 return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); |
| 482 | 482 |
| 483 - if (!CXXTypeInfoDecl) { | 483 - if (!CXXTypeInfoDecl) { |
| 484 - IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info"); | 484 - IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info"); |
| 485 - LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName); | 485 - LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName); |
| 486 - LookupQualifiedName(R, getStdNamespace()); | 486 - LookupQualifiedName(R, getStdNamespace()); |
| 487 - CXXTypeInfoDecl = R.getAsSingle<RecordDecl>(); | 487 - CXXTypeInfoDecl = R.getAsSingle<RecordDecl>(); |
| 488 - // Microsoft's typeinfo doesn't have type_info in std but in the global | 488 - // Microsoft's typeinfo doesn't have type_info in std but in the global |
| 489 - // namespace if _HAS_EXCEPTIONS is defined to 0. See PR13153. | 489 - // namespace if _HAS_EXCEPTIONS is defined to 0. See PR13153. |
| 490 - if (!CXXTypeInfoDecl && LangOpts.MicrosoftMode) { | 490 - if (!CXXTypeInfoDecl && LangOpts.MSVCCompat) { |
| 491 - LookupQualifiedName(R, Context.getTranslationUnitDecl()); | 491 - LookupQualifiedName(R, Context.getTranslationUnitDecl()); |
| 492 - CXXTypeInfoDecl = R.getAsSingle<RecordDecl>(); | 492 - CXXTypeInfoDecl = R.getAsSingle<RecordDecl>(); |
| 493 - } | 493 - } |
| 494 - if (!CXXTypeInfoDecl) | 494 - if (!CXXTypeInfoDecl) |
| 495 - return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); | 495 - return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); |
| 496 - } | 496 - } |
| 497 + RecordDecl* TypeInfoDecl = getOrCreateCXXTypeInfoDecl(); | 497 + RecordDecl* TypeInfoDecl = getOrCreateCXXTypeInfoDecl(); |
| 498 + if (!TypeInfoDecl) | 498 + if (!TypeInfoDecl) |
| 499 + return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); | 499 + return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); |
| 500 | 500 |
| 501 if (!getLangOpts().RTTI) { | 501 if (!getLangOpts().RTTI) { |
| 502 return ExprError(Diag(OpLoc, diag::err_no_typeid_with_fno_rtti)); | 502 return ExprError(Diag(OpLoc, diag::err_no_typeid_with_fno_rtti)); |
| 503 } | 503 } |
| 504 | 504 |
| 505 - QualType TypeInfoType = Context.getTypeDeclType(CXXTypeInfoDecl); | 505 - QualType TypeInfoType = Context.getTypeDeclType(CXXTypeInfoDecl); |
| 506 + QualType TypeInfoType = Context.getTypeDeclType(TypeInfoDecl); | 506 + QualType TypeInfoType = Context.getTypeDeclType(TypeInfoDecl); |
| 507 | 507 |
| 508 if (isType) { | 508 if (isType) { |
| 509 // The operand is a type; handle it as such. | 509 // The operand is a type; handle it as such. |
| 510 @@ -1477,13 +1466,74 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, | 510 @@ -1539,13 +1528,74 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, |
| 511 } | 511 } |
| 512 } | 512 } |
| 513 | 513 |
| 514 - return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, | 514 - return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, |
| 515 + CXXNewExpr* Result = | 515 + CXXNewExpr* Result = |
| 516 + new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, | 516 + new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, |
| 517 OperatorDelete, | 517 OperatorDelete, |
| 518 UsualArrayDeleteWantsSize, | 518 UsualArrayDeleteWantsSize, |
| 519 PlacementArgs, TypeIdParens, | 519 PlacementArgs, TypeIdParens, |
| 520 ArraySize, initStyle, Initializer, | 520 ArraySize, initStyle, Initializer, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 + default: | 577 + default: |
| 578 + ; | 578 + ; |
| 579 + } | 579 + } |
| 580 + } | 580 + } |
| 581 + } | 581 + } |
| 582 + | 582 + |
| 583 + return Owned(Result); | 583 + return Owned(Result); |
| 584 } | 584 } |
| 585 | 585 |
| 586 /// \brief Checks that a type is suitable as the allocated type | 586 /// \brief Checks that a type is suitable as the allocated type |
| 587 @@ -1929,6 +1979,82 @@ void Sema::DeclareGlobalNewDelete() { | 587 @@ -2037,6 +2087,82 @@ void Sema::DeclareGlobalNewDelete() { |
| 588 Context.VoidTy, VoidPtr); | 588 } |
| 589 } | 589 } |
| 590 | 590 |
| 591 +/// DeclareGlobalAllocatorInterceptFunctions - Declares a single implicit globa
l | 591 +/// DeclareGlobalAllocatorInterceptFunctions - Declares a single implicit globa
l |
| 592 +/// allocator intercept functions if it doesn't already exist. | 592 +/// allocator intercept functions if it doesn't already exist. |
| 593 +void Sema::DeclareGlobalAllocatorInterceptFunctions(DeclarationName Name) { | 593 +void Sema::DeclareGlobalAllocatorInterceptFunctions(DeclarationName Name) { |
| 594 + DeclContext *GlobalCtx = Context.getTranslationUnitDecl(); | 594 + DeclContext *GlobalCtx = Context.getTranslationUnitDecl(); |
| 595 + | 595 + |
| 596 + QualType VoidPtrType = Context.getPointerType(Context.VoidTy); | 596 + QualType VoidPtrType = Context.getPointerType(Context.VoidTy); |
| 597 + QualType SizeType = Context.getSizeType(); | 597 + QualType SizeType = Context.getSizeType(); |
| 598 + | 598 + |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 660 + | 660 + |
| 661 + // FIXME: Also add this declaration to the IdentifierResolver, but | 661 + // FIXME: Also add this declaration to the IdentifierResolver, but |
| 662 + // make sure it is at the end of the chain to coincide with the | 662 + // make sure it is at the end of the chain to coincide with the |
| 663 + // global scope. | 663 + // global scope. |
| 664 + Context.getTranslationUnitDecl()->addDecl(Intercept); | 664 + Context.getTranslationUnitDecl()->addDecl(Intercept); |
| 665 +} | 665 +} |
| 666 + | 666 + |
| 667 /// DeclareGlobalAllocationFunction - Declares a single implicit global | 667 /// DeclareGlobalAllocationFunction - Declares a single implicit global |
| 668 /// allocation function if it doesn't already exist. | 668 /// allocation function if it doesn't already exist. |
| 669 void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, | 669 void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, |
| 670 @@ -2302,10 +2428,70 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGl
obal, | 670 @@ -2449,10 +2575,70 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGl
obal, |
| 671 } | 671 } |
| 672 } | 672 } |
| 673 | 673 |
| 674 - return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm
, | 674 - return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm
, |
| 675 - ArrayFormAsWritten, | 675 - ArrayFormAsWritten, |
| 676 - UsualArrayDeleteWantsSize, | 676 - UsualArrayDeleteWantsSize, |
| 677 - OperatorDelete, Ex.take(), StartLoc)
); | 677 - OperatorDelete, Ex.take(), StartLoc)
); |
| 678 + CXXDeleteExpr* Result = | 678 + CXXDeleteExpr* Result = |
| 679 + new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm, | 679 + new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm, |
| 680 + ArrayFormAsWritten, | 680 + ArrayFormAsWritten, |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 + default: | 735 + default: |
| 736 + ; | 736 + ; |
| 737 + } | 737 + } |
| 738 + } | 738 + } |
| 739 + } | 739 + } |
| 740 + | 740 + |
| 741 + return Owned(Result); | 741 + return Owned(Result); |
| 742 } | 742 } |
| 743 | 743 |
| 744 /// \brief Check the use of the given variable as a C++ condition in an if, | 744 /// \brief Check the use of the given variable as a C++ condition in an if, |
| OLD | NEW |