EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, None);
}
+#ifndef NDEBUG
+// Determine whether the given argument is an Objective-C method
+// that may have type parameters in its signature.
+static bool isObjCMethodWithTypeParams(const ObjCMethodDecl *method) {
+ const DeclContext *dc = method->getDeclContext();
+ if (const ObjCInterfaceDecl *classDecl = dyn_cast<ObjCInterfaceDecl>(dc)) {
+ return classDecl->getTypeParamListAsWritten();
+ }
+
+ if (const ObjCCategoryDecl *catDecl = dyn_cast<ObjCCategoryDecl>(dc)) {
+ return catDecl->getTypeParamList();
+ }
+
+ return false;
+}
+#endif
+
+/// EmitCallArgs - Emit call arguments for a function.
void CodeGenFunction::EmitCallArgs(
- CallArgList &Args, ArrayRef<QualType> ArgTypes,
+ CallArgList &Args, PrototypeWrapper Prototype,
llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,
AbstractCallee AC, unsigned ParamsToSkip, EvaluationOrder Order) {
+ SmallVector<QualType, 16> ArgTypes;
+
+ assert((ParamsToSkip == 0 || Prototype.P) &&
+ "Can't skip parameters if type info is not provided");
+
+ // First, use the argument types that the type info knows about
+ bool IsVariadic = false;
+ if (Prototype.P) {
+ const auto *MD = Prototype.P.dyn_cast<const ObjCMethodDecl *>();
+ if (MD) {
+ IsVariadic = MD->isVariadic();
+ ArgTypes.assign(MD->param_type_begin() + ParamsToSkip,
+ MD->param_type_end());
+ } else {
+ const auto *FPT = Prototype.P.get<const FunctionProtoType *>();
+ IsVariadic = FPT->isVariadic();
+ ArgTypes.assign(FPT->param_type_begin() + ParamsToSkip,
+ FPT->param_type_end());
+ }
+
+#ifndef NDEBUG
+ // Check that the prototyped types match the argument expression types.
+ bool isGenericMethod = MD && isObjCMethodWithTypeParams(MD);
+ CallExpr::const_arg_iterator Arg = ArgRange.begin();
+ for (QualType Ty : ArgTypes) {
+ assert(Arg != ArgRange.end() && "Running over edge of argument list!");
+ assert(
+ (isGenericMethod || Ty->isVariablyModifiedType() ||
+ Ty.getNonReferenceType()->isObjCRetainableType() ||
+ getContext()
+ .getCanonicalType(Ty.getNonReferenceType())
+ .getTypePtr() ==
+ getContext().getCanonicalType((*Arg)->getType()).getTypePtr()) &&
+ "type mismatch in call argument!");
+ ++Arg;
+ }
+
+ // Either we've emitted all the call args, or we have a call to variadic
+ // function.
+ assert((Arg == ArgRange.end() || IsVariadic) &&
+ "Extra arguments in non-variadic function!");
+#endif
+ }
+
+ // If we still have any arguments, emit them using the type of the argument.
+ for (auto *A : llvm::make_range(std::next(ArgRange.begin(), ArgTypes.size()),
+ ArgRange.end()))
+ ArgTypes.push_back(IsVariadic ? getVarArgType(A) : A->getType());
assert((int)ArgTypes.size() == (ArgRange.end() - ArgRange.begin()));
- // We *have* to evaluate arguments from right to left in the MS C++ ABI,
+ // We must evaluate arguments from right to left in the MS C++ ABI,
// because arguments are destroyed left to right in the callee. As a special
// case, there are certain language constructs that require left-to-right
// evaluation, and in those cases we consider the evaluation order requirement
const CallExpr *TheCall,
bool IsDelete) {
CallArgList Args;
- EmitCallArgs(Args, Type->getParamTypes(), TheCall->arguments());
+ EmitCallArgs(Args, Type, TheCall->arguments());
// Find the allocation or deallocation function that we're calling.
ASTContext &Ctx = getContext();
DeclarationName Name = Ctx.DeclarationNames
Address Loc);
public:
-#ifndef NDEBUG
- // Determine whether the given argument is an Objective-C method
- // that may have type parameters in its signature.
- static bool isObjCMethodWithTypeParams(const ObjCMethodDecl *method) {
- const DeclContext *dc = method->getDeclContext();
- if (const ObjCInterfaceDecl *classDecl= dyn_cast<ObjCInterfaceDecl>(dc)) {
- return classDecl->getTypeParamListAsWritten();
- }
-
- if (const ObjCCategoryDecl *catDecl = dyn_cast<ObjCCategoryDecl>(dc)) {
- return catDecl->getTypeParamList();
- }
-
- return false;
- }
-
- template<typename T>
- static bool isObjCMethodWithTypeParams(const T *) { return false; }
-#endif
-
enum class EvaluationOrder {
///! No language constraints on evaluation order.
Default,
ForceRightToLeft
};
- /// EmitCallArgs - Emit call arguments for a function.
- template <typename T>
- void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo,
- llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,
- AbstractCallee AC = AbstractCallee(),
- unsigned ParamsToSkip = 0,
- EvaluationOrder Order = EvaluationOrder::Default) {
- SmallVector<QualType, 16> ArgTypes;
- CallExpr::const_arg_iterator Arg = ArgRange.begin();
-
- assert((ParamsToSkip == 0 || CallArgTypeInfo) &&
- "Can't skip parameters if type info is not provided");
- if (CallArgTypeInfo) {
-#ifndef NDEBUG
- bool isGenericMethod = isObjCMethodWithTypeParams(CallArgTypeInfo);
-#endif
-
- // First, use the argument types that the type info knows about
- for (auto I = CallArgTypeInfo->param_type_begin() + ParamsToSkip,
- E = CallArgTypeInfo->param_type_end();
- I != E; ++I, ++Arg) {
- assert(Arg != ArgRange.end() && "Running over edge of argument list!");
- assert((isGenericMethod ||
- ((*I)->isVariablyModifiedType() ||
- (*I).getNonReferenceType()->isObjCRetainableType() ||
- getContext()
- .getCanonicalType((*I).getNonReferenceType())
- .getTypePtr() ==
- getContext()
- .getCanonicalType((*Arg)->getType())
- .getTypePtr())) &&
- "type mismatch in call argument!");
- ArgTypes.push_back(*I);
- }
- }
-
- // Either we've emitted all the call args, or we have a call to variadic
- // function.
- assert((Arg == ArgRange.end() || !CallArgTypeInfo ||
- CallArgTypeInfo->isVariadic()) &&
- "Extra arguments in non-variadic function!");
-
- // If we still have any arguments, emit them using the type of the argument.
- for (auto *A : llvm::make_range(Arg, ArgRange.end()))
- ArgTypes.push_back(CallArgTypeInfo ? getVarArgType(A) : A->getType());
+ // Wrapper for function prototype sources. Wraps either a FunctionProtoType or
+ // an ObjCMethodDecl.
+ struct PrototypeWrapper {
+ llvm::PointerUnion<const FunctionProtoType *, const ObjCMethodDecl *> P;
- EmitCallArgs(Args, ArgTypes, ArgRange, AC, ParamsToSkip, Order);
- }
+ PrototypeWrapper(const FunctionProtoType *FT) : P(FT) {}
+ PrototypeWrapper(const ObjCMethodDecl *MD) : P(MD) {}
+ };
- void EmitCallArgs(CallArgList &Args, ArrayRef<QualType> ArgTypes,
+ void EmitCallArgs(CallArgList &Args, PrototypeWrapper Prototype,
llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,
AbstractCallee AC = AbstractCallee(),
unsigned ParamsToSkip = 0,