case OCOMPLEX:
                ok |= Erv;
-               if(twoarg(n) < 0)
-                       goto error;
-               l = typecheck(&n->left, Erv | (top & Eiota));
-               r = typecheck(&n->right, Erv | (top & Eiota));
-               if(l->type == T || r->type == T)
-                       goto error;
-               defaultlit2(&l, &r, 0);
-               if(l->type == T || r->type == T)
-                       goto error;
-               n->left = l;
-               n->right = r;
+               if(count(n->list) == 1) {
+                       typechecklist(n->list, Efnstruct);
+                       t = n->list->n->left->type;
+                       if(t->outtuple != 2) {
+                               yyerror("invalid operation: complex expects two arguments, %N returns %d results", n->list->n, t->outtuple);
+                               goto error;
+                       }
+                       t = n->list->n->type->type;
+                       l = t->nname;
+                       r = t->down->nname;
+               } else {
+                       if(twoarg(n) < 0)
+                               goto error;
+                       l = typecheck(&n->left, Erv | (top & Eiota));
+                       r = typecheck(&n->right, Erv | (top & Eiota));
+                       if(l->type == T || r->type == T)
+                               goto error;
+                       defaultlit2(&l, &r, 0);
+                       if(l->type == T || r->type == T)
+                               goto error;
+                       n->left = l;
+                       n->right = r;
+               }
                if(!eqtype(l->type, r->type)) {
                        yyerror("invalid operation: %N (mismatched types %T and %T)", n, l->type, r->type);
                        goto error;
                        yyerror("missing arguments to append");
                        goto error;
                }
-               typechecklist(args, Erv);
+
+               if(count(args) == 1 && !n->isddd)
+                       typecheck(&args->n, Erv | Efnstruct);
+               else
+                       typechecklist(args, Erv);
+
                if((t = args->n->type) == T)
                        goto error;
+
+               // Unpack multiple-return result before type-checking.
+               if(istype(t, TSTRUCT)) {
+                       t = t->type;
+                       if(istype(t, TFIELD))
+                               t = t->type;
+               }
+
                n->type = t;
                if(!isslice(t)) {
                        if(isconst(args->n, CTNIL)) {
 
        case OADD:
        case OCOMPLEX:
        case OLROT:
+               // Use results from call expression as arguments for complex.
+               if(n->op == OCOMPLEX && n->left == N && n->right == N) {
+                       n->left = n->list->n;
+                       n->right = n->list->next->n;
+               }
                walkexpr(&n->left, init);
                walkexpr(&n->right, init);
                goto ret;
                l->n = cheapexpr(l->n, init);
 
        nsrc = n->list->n;
+
+       // Resolve slice type of multi-valued return.
+       if(istype(nsrc->type, TSTRUCT))
+               nsrc->type = nsrc->type->type->type;
        argc = count(n->list) - 1;
        if (argc < 1) {
                return nsrc;
 
--- /dev/null
+// run
+
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 5793: calling 2-arg builtin with multiple-result f() call expression gives
+// spurious error.
+
+package main
+
+func complexArgs() (float64, float64) {
+       return 5, 7
+}
+
+func appendArgs() ([]string, string) {
+       return []string{"foo"}, "bar"
+}
+
+func appendMultiArgs() ([]byte, byte, byte) {
+       return []byte{'a', 'b'}, '1', '2'
+}
+
+func main() {
+       if c := complex(complexArgs()); c != 5+7i {
+               panic(c)
+       }
+
+       if s := append(appendArgs()); len(s) != 2 || s[0] != "foo" || s[1] != "bar" {
+               panic(s)
+       }
+
+       if b := append(appendMultiArgs()); len(b) != 4 || b[0] != 'a' || b[1] != 'b' || b[2] != '1' || b[3] != '2' {
+               panic(b)
+       }
+}