@@ -722,20 +722,18 @@ func (p *Package) mangleName(n *Name) {
722
722
func (p * Package ) rewriteCalls (f * File ) bool {
723
723
needsUnsafe := false
724
724
// Walk backward so that in C.f1(C.f2()) we rewrite C.f2 first.
725
- for i := len (f .Calls ) - 1 ; i >= 0 ; i -- {
726
- call := f .Calls [i ]
727
- // This is a call to C.xxx; set goname to "xxx".
728
- goname := call .Call .Fun .(* ast.SelectorExpr ).Sel .Name
729
- if goname == "malloc" {
725
+ for _ , call := range f .Calls {
726
+ if call .Done {
730
727
continue
731
728
}
732
- name := f .Name [goname ]
733
- if name .Kind != "func" {
734
- // Probably a type conversion.
735
- continue
736
- }
737
- if p .rewriteCall (f , call , name ) {
738
- needsUnsafe = true
729
+ start := f .offset (call .Call .Pos ())
730
+ end := f .offset (call .Call .End ())
731
+ str , nu := p .rewriteCall (f , call )
732
+ if str != "" {
733
+ f .Edit .Replace (start , end , str )
734
+ if nu {
735
+ needsUnsafe = true
736
+ }
739
737
}
740
738
}
741
739
return needsUnsafe
@@ -745,16 +743,37 @@ func (p *Package) rewriteCalls(f *File) bool {
745
743
// If any pointer checks are required, we rewrite the call into a
746
744
// function literal that calls _cgoCheckPointer for each pointer
747
745
// argument and then calls the original function.
748
- // This returns whether the package needs to import unsafe as _cgo_unsafe.
749
- func (p * Package ) rewriteCall (f * File , call * Call , name * Name ) bool {
746
+ // This returns the rewritten call and whether the package needs to
747
+ // import unsafe as _cgo_unsafe.
748
+ // If it returns the empty string, the call did not need to be rewritten.
749
+ func (p * Package ) rewriteCall (f * File , call * Call ) (string , bool ) {
750
+ // This is a call to C.xxx; set goname to "xxx".
751
+ // It may have already been mangled by rewriteName.
752
+ var goname string
753
+ switch fun := call .Call .Fun .(type ) {
754
+ case * ast.SelectorExpr :
755
+ goname = fun .Sel .Name
756
+ case * ast.Ident :
757
+ goname = strings .TrimPrefix (fun .Name , "_C2func_" )
758
+ goname = strings .TrimPrefix (goname , "_Cfunc_" )
759
+ }
760
+ if goname == "" || goname == "malloc" {
761
+ return "" , false
762
+ }
763
+ name := f .Name [goname ]
764
+ if name == nil || name .Kind != "func" {
765
+ // Probably a type conversion.
766
+ return "" , false
767
+ }
768
+
750
769
params := name .FuncType .Params
751
770
args := call .Call .Args
752
771
753
772
// Avoid a crash if the number of arguments is
754
773
// less than the number of parameters.
755
774
// This will be caught when the generated file is compiled.
756
775
if len (args ) < len (params ) {
757
- return false
776
+ return "" , false
758
777
}
759
778
760
779
any := false
@@ -765,7 +784,7 @@ func (p *Package) rewriteCall(f *File, call *Call, name *Name) bool {
765
784
}
766
785
}
767
786
if ! any {
768
- return false
787
+ return "" , false
769
788
}
770
789
771
790
// We need to rewrite this call.
@@ -848,7 +867,10 @@ func (p *Package) rewriteCall(f *File, call *Call, name *Name) bool {
848
867
// Write _cgoCheckPointer calls to sbCheck.
849
868
var sbCheck bytes.Buffer
850
869
for i , param := range params {
851
- arg := p .mangle (f , & args [i ])
870
+ arg , nu := p .mangle (f , & args [i ])
871
+ if nu {
872
+ needsUnsafe = true
873
+ }
852
874
853
875
// Explicitly convert untyped constants to the
854
876
// parameter type, to avoid a type mismatch.
@@ -893,12 +915,12 @@ func (p *Package) rewriteCall(f *File, call *Call, name *Name) bool {
893
915
sb .WriteString ("return " )
894
916
}
895
917
896
- // Now we are ready to call the C function.
897
- // To work smoothly with rewriteRef we leave the call in place
898
- // and just replace the old arguments with our new ones.
899
- f .Edit .Insert (f .offset (call .Call .Fun .Pos ()), sb .String ())
918
+ m , nu := p .mangle (f , & call .Call .Fun )
919
+ if nu {
920
+ needsUnsafe = true
921
+ }
922
+ sb .WriteString (gofmtLine (m ))
900
923
901
- sb .Reset ()
902
924
sb .WriteString ("(" )
903
925
for i := range params {
904
926
if i > 0 {
@@ -916,9 +938,7 @@ func (p *Package) rewriteCall(f *File, call *Call, name *Name) bool {
916
938
}
917
939
sb .WriteString ("()" )
918
940
919
- f .Edit .Replace (f .offset (call .Call .Lparen ), f .offset (call .Call .Rparen )+ 1 , sb .String ())
920
-
921
- return needsUnsafe
941
+ return sb .String (), needsUnsafe
922
942
}
923
943
924
944
// needsPointerCheck returns whether the type t needs a pointer check.
@@ -1025,32 +1045,54 @@ func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
1025
1045
}
1026
1046
}
1027
1047
1028
- // mangle replaces references to C names in arg with the mangled names.
1029
- // It removes the corresponding references in f.Ref, so that we don't
1030
- // try to do the replacement again in rewriteRef.
1031
- func (p * Package ) mangle (f * File , arg * ast.Expr ) ast.Expr {
1048
+ // mangle replaces references to C names in arg with the mangled names,
1049
+ // rewriting calls when it finds them.
1050
+ // It removes the corresponding references in f.Ref and f.Calls, so that we
1051
+ // don't try to do the replacement again in rewriteRef or rewriteCall.
1052
+ func (p * Package ) mangle (f * File , arg * ast.Expr ) (ast.Expr , bool ) {
1053
+ needsUnsafe := false
1032
1054
f .walk (arg , ctxExpr , func (f * File , arg interface {}, context astContext ) {
1033
1055
px , ok := arg .(* ast.Expr )
1034
1056
if ! ok {
1035
1057
return
1036
1058
}
1037
1059
sel , ok := (* px ).(* ast.SelectorExpr )
1038
- if ! ok {
1060
+ if ok {
1061
+ if l , ok := sel .X .(* ast.Ident ); ! ok || l .Name != "C" {
1062
+ return
1063
+ }
1064
+
1065
+ for _ , r := range f .Ref {
1066
+ if r .Expr == px {
1067
+ * px = p .rewriteName (f , r )
1068
+ r .Done = true
1069
+ break
1070
+ }
1071
+ }
1072
+
1039
1073
return
1040
1074
}
1041
- if l , ok := sel .X .(* ast.Ident ); ! ok || l .Name != "C" {
1075
+
1076
+ call , ok := (* px ).(* ast.CallExpr )
1077
+ if ! ok {
1042
1078
return
1043
1079
}
1044
1080
1045
- for _ , r := range f .Ref {
1046
- if r .Expr == px {
1047
- * px = p .rewriteName (f , r )
1048
- r .Done = true
1049
- break
1081
+ for _ , c := range f .Calls {
1082
+ if ! c .Done && c .Call .Lparen == call .Lparen {
1083
+ cstr , nu := p .rewriteCall (f , c )
1084
+ if cstr != "" {
1085
+ // Smuggle the rewritten call through an ident.
1086
+ * px = ast .NewIdent (cstr )
1087
+ if nu {
1088
+ needsUnsafe = true
1089
+ }
1090
+ c .Done = true
1091
+ }
1050
1092
}
1051
1093
}
1052
1094
})
1053
- return * arg
1095
+ return * arg , needsUnsafe
1054
1096
}
1055
1097
1056
1098
// checkIndex checks whether arg the form &a[i], possibly inside type
0 commit comments