diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 1828dc6c0408..962eb5d41a9e 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3943,23 +3943,33 @@ bool Sema::SemaBuiltinVAStartARM(CallExpr *Call) { if (checkVAStartIsInVariadicFunction(*this, Func)) return true; - const struct { - unsigned ArgNo; - QualType Type; - } ArgumentTypes[] = { - { 1, Context.getPointerType(Context.CharTy.withConst()) }, - { 2, Context.getSizeType() }, - }; + // __va_start on Windows does not validate the parameter qualifiers - 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; - } + 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; } diff --git a/clang/test/SemaCXX/microsoft-varargs.cpp b/clang/test/SemaCXX/microsoft-varargs.cpp index 35f31a97c4f1..5b0f90eb5ca0 100644 --- a/clang/test/SemaCXX/microsoft-varargs.cpp +++ b/clang/test/SemaCXX/microsoft-varargs.cpp @@ -20,3 +20,8 @@ int builtin(int i, ...) { return __builtin_va_arg(ap, int); } +void test___va_start_ignore_const(const char *format, ...) { + va_list args; + ((void)(__va_start(&args, (&const_cast(reinterpret_cast(format))), ((sizeof(format) + 4 - 1) & ~(4 - 1)), (&const_cast(reinterpret_cast(format)))))); +} +