]> granicus.if.org Git - clang/commitdiff
Add stricter checking for va_arg.
authorEli Friedman <eli.friedman@gmail.com>
Sat, 16 May 2009 12:46:54 +0000 (12:46 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Sat, 16 May 2009 12:46:54 +0000 (12:46 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71942 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
test/Sema/va_arg_x86_32.c [new file with mode: 0644]

index ea0d22ce253e5efff3c120f5e76e6d00689e9969..4145be6ab7659b80f2695755740c9b009878f527 100644 (file)
@@ -5208,15 +5208,21 @@ Sema::OwningExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
 
   // Get the va_list type
   QualType VaListType = Context.getBuiltinVaListType();
-  // Deal with implicit array decay; for example, on x86-64,
-  // va_list is an array, but it's supposed to decay to
-  // a pointer for va_arg.
-  if (VaListType->isArrayType())
+  if (VaListType->isArrayType()) {
+    // Deal with implicit array decay; for example, on x86-64,
+    // va_list is an array, but it's supposed to decay to
+    // a pointer for va_arg.
     VaListType = Context.getArrayDecayedType(VaListType);
-  // Make sure the input expression also decays appropriately.
-  UsualUnaryConversions(E);
+    // Make sure the input expression also decays appropriately.
+    UsualUnaryConversions(E);
+  } else {
+    // Otherwise, the va_list argument must be an l-value because
+    // it is modified by va_arg.
+    if (CheckForModifiableLvalue(E, BuiltinLoc, *this))
+      return ExprError();
+  }
 
-  if (CheckAssignmentConstraints(VaListType, E->getType()) != Compatible) {
+  if (!Context.hasSameType(VaListType, E->getType())) {
     return ExprError(Diag(E->getLocStart(),
                          diag::err_first_argument_to_va_arg_not_of_type_va_list)
       << OrigExpr->getType() << E->getSourceRange());
diff --git a/test/Sema/va_arg_x86_32.c b/test/Sema/va_arg_x86_32.c
new file mode 100644 (file)
index 0000000..850d324
--- /dev/null
@@ -0,0 +1,6 @@
+// RUN: clang-cc -fsyntax-only -verify -triple=i686-pc-linux-gnu %s
+
+int a() {
+  __builtin_va_arg((char*)0, int); // expected-error {{expression is not assignable}}
+  __builtin_va_arg((void*){0}, int); // expected-error {{first argument to 'va_arg' is of type 'void *'}}
+}