diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 6 | ||||
| -rw-r--r-- | clang/test/CodeGen/le32-vaarg.c | 28 |
2 files changed, 33 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 3395bd7d33b..ef56c0b06f2 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -935,7 +935,11 @@ void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType()); if (!ArgPtr) { - CGF.ErrorUnsupported(VE, "aggregate va_arg expression"); + // If EmitVAArg fails, we fall back to the LLVM instruction. + llvm::Value *Val = + Builder.CreateVAArg(ArgValue, CGF.ConvertType(VE->getType())); + if (!Dest.isIgnored()) + Builder.CreateStore(Val, Dest.getAddr()); return; } diff --git a/clang/test/CodeGen/le32-vaarg.c b/clang/test/CodeGen/le32-vaarg.c new file mode 100644 index 00000000000..51bbb029684 --- /dev/null +++ b/clang/test/CodeGen/le32-vaarg.c @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple le32-unknown-nacl -emit-llvm -o - %s | FileCheck %s +#include <stdarg.h> + +int get_int(va_list *args) { + return va_arg(*args, int); +} +// CHECK: define i32 @get_int +// CHECK: [[RESULT:%[a-z_0-9]+]] = va_arg {{.*}}, i32{{$}} +// CHECK: ret i32 [[RESULT]] + +struct Foo { + int x; +}; + +struct Foo dest; + +void get_struct(va_list *args) { + dest = va_arg(*args, struct Foo); +} +// CHECK: define void @get_struct +// CHECK: [[RESULT:%[a-z_0-9]+]] = va_arg {{.*}}, %struct.Foo{{$}} +// CHECK: store %struct.Foo [[RESULT]], %struct.Foo* @dest + +void skip_struct(va_list *args) { + va_arg(*args, struct Foo); +} +// CHECK: define void @skip_struct +// CHECK: va_arg {{.*}}, %struct.Foo{{$}} |

