Index: lib/CodeGen/CGVTables.cpp =================================================================== --- lib/CodeGen/CGVTables.cpp +++ lib/CodeGen/CGVTables.cpp @@ -322,8 +322,6 @@ // Consider return adjustment if we have ThunkInfo. if (Thunk && !Thunk->Return.isEmpty()) RV = PerformReturnAdjustment(*this, ResultType, RV, *Thunk); - else if (llvm::CallInst* Call = dyn_cast(CallOrInvoke)) - Call->setTailCallKind(llvm::CallInst::TCK_Tail); // Emit return. if (!ResultType->isVoidType() && Slot.isNull()) Index: test/CodeGenCXX/microsoft-abi-structors.cpp =================================================================== --- test/CodeGenCXX/microsoft-abi-structors.cpp +++ test/CodeGenCXX/microsoft-abi-structors.cpp @@ -177,7 +177,7 @@ // Do an adjustment from B* to C*. // DTORS2: getelementptr i8, i8* %{{.*}}, i32 -4 // DTORS2: bitcast i8* %{{.*}} to %"struct.dtor_in_second_nvbase::C"* -// DTORS2: %[[CALL:.*]] = tail call x86_thiscallcc i8* @"\01??_GC@dtor_in_second_nvbase@@UAEPAXI@Z" +// DTORS2: %[[CALL:.*]] = call x86_thiscallcc i8* @"\01??_GC@dtor_in_second_nvbase@@UAEPAXI@Z" // DTORS2: ret i8* %[[CALL]] } Index: test/CodeGenCXX/tail-byval.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/tail-byval.cpp @@ -0,0 +1,112 @@ +// RUN: %clang_cc1 %s -I%S -isystem %S/Inputs -emit-llvm -triple i386-apple-darwin9 -Wno-incompatible-ms-struct -o - -Os | opt - -dse -S -o - | FileCheck %s +#pragma ms_struct on + +#include +#include + +extern "C" int rand(); + +struct +IByteStream +{ +public: +}; + + +class IEmpty {}; + +class CRepro +{ +protected: + CRepro( IEmpty* p) : mp(p) {}; + virtual ~CRepro() {} + + IEmpty* mp; +}; + +class BStream : public CRepro, public IByteStream +{ +protected: + BStream( IEmpty *p); + virtual ~BStream(){} ; + +protected: + int32_t Ref; +}; + +class CStream : public BStream +{ +public: + static uint32_t Create(uint32_t m, IByteStream **ppS, IEmpty *p); +private: + CStream(bool fD, bool fZero, IEmpty *p) ; +}; + +typedef union _LARGE { + struct { + uint32_t Low; + int32_t High; + } DUMMYSTRUCTNAME; + struct { + uint32_t Low; + int32_t High; + } u; + int64_t Quad; +} LARGE; + +class I +{ +public: + virtual uint32_t Seek(LARGE dlibMove, uint32_t Origin, LARGE *plibNP) = 0; + +}; + +class CBase : public CRepro +{ +protected: + CBase(IByteStream *ps, IEmpty *p); + virtual ~CBase() {}; + +protected: + uint64_t Offset; + uint32_t ThreadId; +}; + +class C : public CBase, public I +{ +public: + static uint32_t Create(IByteStream *ps, wchar_t *w, I **ppi, IEmpty *p); + uint32_t Seek(LARGE dlibMove, uint32_t Origin, LARGE *plibNP); + +private: + C(IByteStream *ps, IEmpty *p) ; + ~C() {}; + +}; + +uint32_t C::Seek(LARGE dlibMove, uint32_t Origin, LARGE *plibNP) +{ + uint32_t hr = 1; + + if (Origin != 1 || dlibMove.Quad != 0) + { + if (ThreadId != 0 && ThreadId != (uint32_t)rand()) + { + hr = 3; + goto LError; + } + + if (Origin == 0) + { + Offset = (uint64_t) dlibMove.Quad; + } + } + +LError: + if (plibNP != NULL) + (*plibNP).Quad = Offset; + return hr; +} +// CHECK: define i32 @_ZThn20_N1C4SeekE6_LARGEjPS0_ +// CHECK: store i64 +// CHECK: ret