} else {
FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
}
- } else if (IsRegCall && FI.getReturnType()->getAs<ComplexType>()) {
+ } else if (IsRegCall && FI.getReturnType()->getAs<ComplexType>() &&
+ getContext().getCanonicalType(FI.getReturnType()
+ ->getAs<ComplexType>()
+ ->getElementType()) ==
+ getContext().LongDoubleTy)
// Complex Long Double Type is passed in Memory when Regcall
// calling convention is used.
- const ComplexType *CT = FI.getReturnType()->getAs<ComplexType>();
- if (getContext().getCanonicalType(CT->getElementType()) ==
- getContext().LongDoubleTy)
- FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
- } else
+ FI.getReturnInfo() = getIndirectReturnResult(FI.getReturnType());
+ else
FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
}
int a;
public:
#ifndef WIN_TEST
- __regcall
+ __regcall
#endif
test_class(){++x;}
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classC1Ev
// CHECK-WIN32-DAG: define linkonce_odr dso_local x86_thiscallcc %class.test_class* @"??0test_class@@QAE@XZ"
#ifndef WIN_TEST
- __regcall
+ __regcall
#endif
~test_class(){--x;}
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD2Ev
// Windows ignores calling convention on constructor/destructors.
// CHECK-WIN64-DAG: define linkonce_odr dso_local void @"??1test_class@@QEAA@XZ"
// CHECK-WIN32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"??1test_class@@QAE@XZ"
-
+
test_class& __regcall operator+=(const test_class&){
return *this;
}
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_class20__regcall3__do_thingEv
// CHECK-WIN64-DAG: define linkonce_odr dso_local x86_regcallcc void @"?do_thing@test_class@@QEAwXXZ"
// CHECK-WIN32-DAG: define linkonce_odr dso_local x86_regcallcc void @"?do_thing@test_class@@QAwXXZ"
-
+
template<typename T>
void __regcall tempFunc(T i){}
// CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_class20__regcall3__tempFuncIiEEvT_
// CHECK-LIN32-DAG: define x86_regcallcc void @_Z15__regcall3__fooCe({ x86_fp80, x86_fp80 }* inreg noalias sret align 4 %agg.result, { x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 4 %f)
// CHECK-WIN64-DAG: define dso_local x86_regcallcc { double, double } @"?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
// CHECK-WIN32-DAG: define dso_local x86_regcallcc { double, double } @"?foo@@YwU?$_Complex@O@__clang@@U12@@Z"(double %f.0, double %f.1)
+
+// The following caused us to dereference uninitialized memory. The long name
+// seems necessary, as does the return types.
+float _Complex __regcall callee(float _Complex f);
+// CHECK-LIN64-DAG: declare x86_regcallcc <2 x float> @_Z18__regcall3__calleeCf(<2 x float>)
+// CHECK-LIN32-DAG: declare x86_regcallcc { float, float } @_Z18__regcall3__calleeCf(float, float)
+// CHECK-WIN64-DAG: declare dso_local x86_regcallcc { float, float } @"?callee@@YwU?$_Complex@M@__clang@@U12@@Z"(float, float)
+// CHECK-WIN32-DAG: declare dso_local x86_regcallcc { float, float } @"?callee@@YwU?$_Complex@M@__clang@@U12@@Z"(float, float)
+
+__regcall int
+some_really_long_name_that_manages_to_hit_the_right_spot_of_mem(int a) {
+ float _Complex x[2];
+ x[0] = callee(x[0]);
+ return a;
+}