diff options
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 20 | ||||
-rw-r--r-- | clang/test/Sema/va_arg_x86_32.c | 6 |
2 files changed, 19 insertions, 7 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ea0d22ce253..4145be6ab76 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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/clang/test/Sema/va_arg_x86_32.c b/clang/test/Sema/va_arg_x86_32.c new file mode 100644 index 00000000000..850d324dbfc --- /dev/null +++ b/clang/test/Sema/va_arg_x86_32.c @@ -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 *'}} +} |