if (checkVAStartIsInVariadicFunction(*this, Func))
return true;
- const struct {
- unsigned ArgNo;
- QualType Type;
- } ArgumentTypes[] = {
- { 1, Context.getPointerType(Context.CharTy.withConst()) },
- { 2, Context.getSizeType() },
- };
-
- for (const auto &AT : ArgumentTypes) {
- const Expr *Arg = Call->getArg(AT.ArgNo)->IgnoreParens();
- if (Arg->getType().getCanonicalType() == AT.Type.getCanonicalType())
- continue;
- Diag(Arg->getLocStart(), diag::err_typecheck_convert_incompatible)
- << Arg->getType() << AT.Type << 1 /* different class */
- << 0 /* qualifier difference */ << 3 /* parameter mismatch */
- << AT.ArgNo + 1 << Arg->getType() << AT.Type;
- }
+ // __va_start on Windows does not validate the parameter qualifiers
+
+ const Expr *Arg1 = Call->getArg(1)->IgnoreParens();
+ const Type *Arg1Ty = Arg1->getType().getCanonicalType().getTypePtr();
+
+ const Expr *Arg2 = Call->getArg(2)->IgnoreParens();
+ const Type *Arg2Ty = Arg2->getType().getCanonicalType().getTypePtr();
+
+ const QualType &ConstCharPtrTy =
+ Context.getPointerType(Context.CharTy.withConst());
+ if (!Arg1Ty->isPointerType() ||
+ Arg1Ty->getPointeeType().withoutLocalFastQualifiers() != Context.CharTy)
+ Diag(Arg1->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << Arg1->getType() << ConstCharPtrTy
+ << 1 /* different class */
+ << 0 /* qualifier difference */
+ << 3 /* parameter mismatch */
+ << 2 << Arg1->getType() << ConstCharPtrTy;
+
+ const QualType SizeTy = Context.getSizeType();
+ if (Arg2Ty->getCanonicalTypeInternal().withoutLocalFastQualifiers() != SizeTy)
+ Diag(Arg2->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << Arg2->getType() << SizeTy
+ << 1 /* different class */
+ << 0 /* qualifier difference */
+ << 3 /* parameter mismatch */
+ << 3 << Arg2->getType() << SizeTy;
return false;
}