]> granicus.if.org Git - clang/commitdiff
Sema: Windows/ARM __va_start is not const correct
authorSaleem Abdulrasool <compnerd@compnerd.org>
Tue, 26 Sep 2017 17:44:10 +0000 (17:44 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Tue, 26 Sep 2017 17:44:10 +0000 (17:44 +0000)
The `__va_start` intrinsic for Windows ARM does not account for const
correctness when performing a check.  All local qualifiers are ignored
when validating the invocation.  This was exposed by building the swift
stdlib against the Windows 10586 SDK for ARM.  Simply expand out the
check for the two parameters and ignore the qualifiers for the check.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@314226 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaChecking.cpp
test/SemaCXX/microsoft-varargs.cpp

index 1828dc6c0408ae9a295852e02629b3f199c81d12..962eb5d41a9e7e6c08520b958025126d2cfd741e 100644 (file)
@@ -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() },
-  };
-
-  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;
 }
index 35f31a97c4f1679a6dda8fdac6600cfc47ca1fe5..5b0f90eb5ca045c63dda73c4887b9946108685da 100644 (file)
@@ -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<char &>(reinterpret_cast<const volatile char &>(format))), ((sizeof(format) + 4 - 1) & ~(4 - 1)), (&const_cast<char &>(reinterpret_cast<const volatile char &>(format))))));
+}
+