summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
Commit message (Collapse)AuthorAgeFilesLines
* [MS] Fix bug in method vfptr location codeReid Kleckner2018-03-281-0/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We were assuming that vbtable indices were assigned in layout order in our comparison, which is not the case. When a virtual method, such as the destructor, appears in multiple vftables, the vftable that appears first in object layout order is the one that points to the main implementation of that method. The later vftables use thunks. In this layout, we adjusted "this" in the main implementation by the amount that is appropriate for 'B' instead of 'A', even though the main implementation is found in D's vftable for A: struct A { virtual ~A() {} }; struct B { virtual ~B() {} }; struct C : virtual B {}; struct D : virtual A, C {}; D's layout looks like: 0 D subobject (empty) 0 C base suboject 8 A base subobject 16 B base subobject With this fix, we correctly adjust by -8 in D's deleting destructor instead of -16. Fixes PR36921. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@328723 91177308-0d34-0410-b5e6-96231b3b80d8
* [MS] Don't escape MS C++ names with \01Reid Kleckner2018-03-161-41/+41
| | | | | | | It is not needed after LLVM r327734. Now it will be easier to copy-paste IR symbol names from Clang. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@327738 91177308-0d34-0410-b5e6-96231b3b80d8
* Bring r325915 back.Rafael Espindola2018-02-231-21/+21
| | | | | | | | | | | | | | | The tests that failed on a windows host have been fixed. Original message: Start setting dso_local for COFF. With this there are still some GVs where we don't set dso_local because setGVProperties is never called. I intend to fix that in followup commits. This is just the bare minimum to teach shouldAssumeDSOLocal what it should do for COFF. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@325940 91177308-0d34-0410-b5e6-96231b3b80d8
* Revert "Start setting dso_local for COFF."Rafael Espindola2018-02-231-21/+21
| | | | | | | | This reverts commit r325915. It will take some time to fix the failures on a windows host. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@325929 91177308-0d34-0410-b5e6-96231b3b80d8
* Start setting dso_local for COFF.Rafael Espindola2018-02-231-21/+21
| | | | | | | | | With this there are still some GVs where we don't set dso_local because setGVProperties is never called. I intend to fix that in followup commits. This is just the bare minimum to teach shouldAssumeDSOLocal what it should do for COFF. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@325915 91177308-0d34-0410-b5e6-96231b3b80d8
* IRGen: Move vtable load after argument evaluation.Peter Collingbourne2018-02-051-15/+15
| | | | | | | | | | | | | | This change reduces the live range of the loaded function pointer, resulting in a slight code size decrease (~10KB in clang), and also improves the security of CFI for virtual calls by making it less likely that the function pointer will be spilled, and ensuring that it is not spilled across a function call boundary. Fixes PR35353. Differential Revision: https://reviews.llvm.org/D42725 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@324286 91177308-0d34-0410-b5e6-96231b3b80d8
* Reland "[CodeGen] Fix crash when a function taking transparent union is ↵Volodymyr Sapsai2018-01-221-2/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | redeclared." When a function taking transparent union is declared as taking one of union members earlier in the translation unit, clang would hit an "Invalid cast" assertion during EmitFunctionProlog. This case corresponds to function f1 in test/CodeGen/transparent-union-redecl.c. We decided to cast i32 to union because after merging function declarations function parameter type becomes int, CGFunctionInfo::ArgInfo type matches with ABIArgInfo type, so we decide it is a trivial case. But these types should also be castable to parameter declaration type which is not the case here. Now the fix is in converting from ABIArgInfo type to VarDecl type and using argument demotion when necessary. Additional tests in Sema/transparent-union.c capture current behavior and make sure there are no regressions. rdar://problem/34949329 Reviewers: rjmccall, rafael Reviewed By: rjmccall Subscribers: aemerson, cfe-commits, kristof.beyls, ahatanak Differential Revision: https://reviews.llvm.org/D41311 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@323156 91177308-0d34-0410-b5e6-96231b3b80d8
* Change memcpy/memove/memset to have dest and source alignment attributes ↵Daniel Neilson2018-01-191-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | (Step 1). Summary: Upstream LLVM is changing the the prototypes of the @llvm.memcpy/memmove/memset intrinsics. This change updates the Clang tests for this change. The @llvm.memcpy/memmove/memset intrinsics currently have an explicit argument which is required to be a constant integer. It represents the alignment of the dest (and source), and so must be the minimum of the actual alignment of the two. This change removes the alignment argument in favour of placing the alignment attribute on the source and destination pointers of the memory intrinsic call. For example, code which used to read: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 100, i32 4, i1 false) will now read call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %dest, i8* align 4 %src, i32 100, i1 false) At this time the source and destination alignments must be the same (Step 1). Step 2 of the change, to be landed shortly, will relax that contraint and allow the source and destination to have different alignments. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@322964 91177308-0d34-0410-b5e6-96231b3b80d8
* Revert "[CodeGen] Fix crash when a function taking transparent union is ↵Volodymyr Sapsai2017-12-211-8/+2
| | | | | | | | | | | | | | redeclared." This reverts commit r321296. It caused performance regressions FAIL: imp.execution_time FAIL: 2007-01-04-KNR-Args.execution_time FAIL: sse_expandfft.execution_time FAIL: sse_stepfft.execution_time git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@321306 91177308-0d34-0410-b5e6-96231b3b80d8
* [CodeGen] Fix crash when a function taking transparent union is redeclared.Volodymyr Sapsai2017-12-211-2/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When a function taking transparent union is declared as taking one of union members earlier in the translation unit, clang would hit an "Invalid cast" assertion during EmitFunctionProlog. This case corresponds to function f1 in test/CodeGen/transparent-union-redecl.c. We decided to cast i32 to union because after merging function declarations function parameter type becomes int, CGFunctionInfo::ArgInfo type matches with ABIArgInfo type, so we decide it is a trivial case. But these types should also be castable to parameter declaration type which is not the case here. The fix is in checking for the trivial case if ABIArgInfo type matches with parameter declaration type. It exposed inconsistency that we check hasScalarEvaluationKind for different types in EmitParmDecl and EmitFunctionProlog, and comment says they should match. Additional tests in Sema/transparent-union.c capture current behavior and make sure there are no regressions. rdar://problem/34949329 Reviewers: rjmccall, rafael Reviewed By: rjmccall Subscribers: aemerson, cfe-commits, kristof.beyls Differential Revision: https://reviews.llvm.org/D41311 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@321296 91177308-0d34-0410-b5e6-96231b3b80d8
* [MS] Apply adjustments after storing 'this'Reid Kleckner2017-11-161-21/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Summary: The MS ABI convention is that the 'this' pointer on entry is the address of the vfptr that was used to make the virtual method call. In other words, the pointer on entry always points to the base subobject that introduced the virtual method. Consider this hierarchy: struct A { virtual void f() = 0; }; struct B { virtual void g() = 0; }; struct C : A, B { void f() override; void g() override; }; On entry to C::g, [ER]CX will contain the address of C's B subobject, and C::g will have to subtract sizeof(A) to recover a pointer to C. Before this change, we applied this adjustment in the prologue and stored the new value into the "this" local variable alloca used for debug info. However, MSVC does not do this, presumably because it is often profitable to fold the adjustment into later field accesses. This creates a problem, because the debugger expects the variable to be unadjusted. Unfortunately, CodeView doesn't have anything like DWARF expressions for computing variables that aren't in the program anymore, so we have to declare 'this' to be the unadjusted value if we want the debugger to see the right value. This has the side benefit that, in optimized builds, the 'this' pointer will usually be available on function entry because it doesn't require any adjustment. Reviewers: hans Subscribers: aprantl, cfe-commits Differential Revision: https://reviews.llvm.org/D40109 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@318440 91177308-0d34-0410-b5e6-96231b3b80d8
* [MS ABI] Correctly mangling vbase destructorsDavid Majnemer2017-02-141-3/+3
| | | | | | | | | | | | | They are a little bit of a special case in the mangling. They are always mangled without taking into account their virtual-ness of the destructor. They are also mangled to return void, unlike the actual destructor. This fixes PR31931. Differential Revision: https://reviews.llvm.org/D29912 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@295010 91177308-0d34-0410-b5e6-96231b3b80d8
* CodeGen: New vtable group representation: struct of vtable arrays.Peter Collingbourne2016-12-131-7/+7
| | | | | | | | | In a future change, this representation will allow us to use the new inrange annotation on getelementptr to allow the optimizer to split vtable groups. Differential Revision: https://reviews.llvm.org/D22296 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@289584 91177308-0d34-0410-b5e6-96231b3b80d8
* [MS] Fix prologue this adjustment when 'this' is passed indirectlyReid Kleckner2016-09-071-1/+1
| | | | | | | | | | | | Move the logic for doing this from the ABI argument lowering into EmitParmDecl, which runs for all parameters. Our codegen is slightly suboptimal in this case, as we may leave behind a dead store after optimization, but it's 32-bit inalloca, and this fixes the bug in a robust way. Fixes PR30293 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@280836 91177308-0d34-0410-b5e6-96231b3b80d8
* [MS ABI] Don't crash when zero-initializing a vbase which contains a vbaseDavid Majnemer2016-05-121-0/+22
| | | | | | | | | | | | | | | | Bases can be zero-initialized: the storage is zero-initialized before the base constructor is run. The MS ABI has a quirk where base VBPtrs are not installed by the base constructor but by the most derived class. In particular, they are installed before the base constructor is run. The derived constructor must be careful to zero-initialize only the bits of the class which haven't already been populated by virtual base pointers. While we correctly avoided this scenario, we didn't handle the case where the base class has virtual bases which have virtual bases. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@269271 91177308-0d34-0410-b5e6-96231b3b80d8
* Fix use of LLVM IR names in lit testReid Kleckner2016-05-031-1/+1
| | | | git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@268419 91177308-0d34-0410-b5e6-96231b3b80d8
* [MS] Pass CalleeDecl to adjustThisArgumentForVirtualFunctionCallReid Kleckner2016-05-031-0/+18
| | | | | | | | | | If we are devirtualizing, then we want to compute the 'this' adjustment of the devirtualized target, not the adjustment of the base's method definition, which is usually zero. Fixes PR27621 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@268418 91177308-0d34-0410-b5e6-96231b3b80d8
* Revert "Change memcpy/memset/memmove to have dest and source alignments."Pete Cooper2015-11-191-1/+1
| | | | | | | | | | This reverts commit r253512. This likely broke the bots in: http://lab.llvm.org:8011/builders/clang-ppc64-elf-linux2/builds/20202 http://bb.pgr.jp/builders/clang-3stage-i686-linux/builds/3787 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@253542 91177308-0d34-0410-b5e6-96231b3b80d8
* Change memcpy/memset/memmove to have dest and source alignments.Pete Cooper2015-11-181-1/+1
| | | | | | | | | | | | | | | | | | | | | | This is a follow on from a similar LLVM commit: r253511. Note, this was reviewed (and more details are in) http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20151109/312083.html These intrinsics currently have an explicit alignment argument which is required to be a constant integer. It represents the alignment of the source and dest, and so must be the minimum of those. This change allows source and dest to each have their own alignments by using the alignment attribute on their arguments. The alignment argument itself is removed. The only code change to clang is hidden in CGBuilder.h which now passes both dest and source alignment to IRBuilder, instead of taking the minimum of dest and source alignments. Reviewed by Hal Finkel. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@253512 91177308-0d34-0410-b5e6-96231b3b80d8
* [MS ABI] Don't zero-initialize vbptrs in basesDavid Majnemer2015-11-021-0/+26
| | | | | | | | | | | | Certain CXXConstructExpr nodes require zero-initialization before a constructor is called. We had a bug in the case where the constructor is called on a virtual base: we zero-initialized the base's vbptr field. A complementary bug is present in MSVC where no zero-initialization occurs for the subobject at all. This fixes PR25370. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@251783 91177308-0d34-0410-b5e6-96231b3b80d8
* Compute and preserve alignment more faithfully in IR-generation.John McCall2015-09-081-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Introduce an Address type to bundle a pointer value with an alignment. Introduce APIs on CGBuilderTy to work with Address values. Change core APIs on CGF/CGM to traffic in Address where appropriate. Require alignments to be non-zero. Update a ton of code to compute and propagate alignment information. As part of this, I've promoted CGBuiltin's EmitPointerWithAlignment helper function to CGF and made use of it in a number of places in the expression emitter. The end result is that we should now be significantly more correct when performing operations on objects that are locally known to be under-aligned. Since alignment is not reliably tracked in the type system, there are inherent limits to this, but at least we are no longer confused by standard operations like derived-to-base conversions and array-to-pointer decay. I've also fixed a large number of bugs where we were applying the complete-object alignment to a pointer instead of the non-virtual alignment, although most of these were hidden by the very conservative approach we took with member alignment. Also, because IRGen now reliably asserts on zero alignments, we should no longer be subject to an absurd but frustrating recurring bug where an incomplete type would report a zero alignment and then we'd naively do a alignmentAtOffset on it and emit code using an alignment equal to the largest power-of-two factor of the offset. We should also now be emitting much more aggressive alignment attributes in the presence of over-alignment. In particular, field access now uses alignmentAtOffset instead of min. Several times in this patch, I had to change the existing code-generation pattern in order to more effectively use the Address APIs. For the most part, this seems to be a strict improvement, like doing pointer arithmetic with GEPs instead of ptrtoint. That said, I've tried very hard to not change semantics, but it is likely that I've failed in a few places, for which I apologize. ABIArgInfo now always carries the assumed alignment of indirect and indirect byval arguments. In order to cut down on what was already a dauntingly large patch, I changed the code to never set align attributes in the IR on non-byval indirect arguments. That is, we still generate code which assumes that indirect arguments have the given alignment, but we don't express this information to the backend except where it's semantically required (i.e. on byvals). This is likely a minor regression for those targets that did provide this information, but it'll be trivial to add it back in a later patch. I partially punted on applying this work to CGBuiltin. Please do not add more uses of the CreateDefaultAligned{Load,Store} APIs; they will be going away eventually. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@246985 91177308-0d34-0410-b5e6-96231b3b80d8
* Update Clang tests to handle explicitly typed load changes in LLVM.David Blaikie2015-02-271-25/+25
| | | | git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@230795 91177308-0d34-0410-b5e6-96231b3b80d8
* Update Clang tests to handle explicitly typed gep changes in LLVM.David Blaikie2015-02-271-43/+43
| | | | git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@230783 91177308-0d34-0410-b5e6-96231b3b80d8
* Cast vtable address points to i32 (...)** to enable more globaloptReid Kleckner2014-12-031-11/+11
| | | | | | | | | | | | We currently use i32 (...)** as the type of the vptr field in the LLVM struct type. LLVM's GlobalOpt prefers any bitcasts to be on the side of the data being stored rather than on the pointer being stored to. Reviewers: majnemer Differential Revision: http://reviews.llvm.org/D5916 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@223267 91177308-0d34-0410-b5e6-96231b3b80d8
* MS ABI: Properly call global delete when invoking virtual destructorsDavid Majnemer2014-10-311-16/+16
| | | | | | | | | | | | | | | | | | | | Summary: The Itanium ABI approach of using offset-to-top isn't possible with the MS ABI, it doesn't have that kind of information lying around. Instead, we do the following: - Call the virtual deleting destructor with the "don't delete the object flag" set. The virtual deleting destructor will return a pointer to 'this' adjusted to the most derived class. - Call the global delete using the adjusted 'this' pointer. Reviewers: rnk Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D5996 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@220993 91177308-0d34-0410-b5e6-96231b3b80d8
* MS ABI: Emit more canonical vbptr stores and loadsReid Kleckner2014-10-221-20/+15
| | | | | | | | This eliminates some i8* GEPs and makes the IR that clang emits a bit more canonical. More work is needed for vftables, but that isn't a clear win so I plan to send it for review. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@220398 91177308-0d34-0410-b5e6-96231b3b80d8
* Add one more test for PR19172Timur Iskhodzhanov2014-03-211-0/+41
| | | | git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@204453 91177308-0d34-0410-b5e6-96231b3b80d8
* Fix PR19172 - wrong this adjustment calculated for virtual destructor in a ↵Timur Iskhodzhanov2014-03-201-0/+42
| | | | | | | | class with complex inheritance Reviewed at http://llvm-reviews.chandlerc.com/D3128 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@204394 91177308-0d34-0410-b5e6-96231b3b80d8
* Fix PR19104: Incorrect handling of non-virtual calls of virtual methodsTimur Iskhodzhanov2014-03-141-0/+38
| | | | | | Reviewed at http://llvm-reviews.chandlerc.com/D3054 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@203949 91177308-0d34-0410-b5e6-96231b3b80d8
* Fix PR18967 -- Bad this adjustment for virtual methods in a diamond virtual ↵Timur Iskhodzhanov2014-03-071-6/+1
| | | | | | inheritance hierarchy git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@203222 91177308-0d34-0410-b5e6-96231b3b80d8
* [MS ABI] Error instead of generating bad vftables for certain virtual ↵Hans Wennborg2014-02-271-1/+6
| | | | | | | | | | | hierarchies (PR18967) Erroring out until we fix the bug means we don't have to keep chasing down this same miscompile in a bunch of different places. Differential Revision: http://llvm-reviews.chandlerc.com/D2890 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@202331 91177308-0d34-0410-b5e6-96231b3b80d8
* Remove the -cxx-abi command-line flag.Hans Wennborg2014-01-141-2/+2
| | | | | | | | | | | | | | | This makes the C++ ABI depend entirely on the target: MS ABI for -win32 triples, Itanium otherwise. It's no longer possible to do weird combinations. To be able to run a test with a specific ABI without constraining it to a specific triple, new substitutions are added to lit: %itanium_abi_triple and %ms_abi_triple can be used to get the current target triple adjusted to the desired ABI. For example, if the test suite is running with the i686-pc-win32 target, %itanium_abi_triple will expand to i686-pc-mingw32. Differential Revision: http://llvm-reviews.chandlerc.com/D2545 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@199250 91177308-0d34-0410-b5e6-96231b3b80d8
* [ms-abi] Always generate complete constructors in the Microsoft C++ ABIReid Kleckner2014-01-131-0/+27
| | | | | | | | Fixes PR18435, where we generated a base ctor instead of a complete ctor, and so failed to construct virtual bases when constructing the complete object. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@199160 91177308-0d34-0410-b5e6-96231b3b80d8
* Use GEPs correctly when adjusting this in MicrosoftCXXABITimur Iskhodzhanov2013-10-221-7/+7
| | | | | | Reviewed at http://llvm-reviews.chandlerc.com/D1977 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@193176 91177308-0d34-0410-b5e6-96231b3b80d8
* [-cxx-abi microsoft] Fix this argument/parameter offsets for virtual ↵Timur Iskhodzhanov2013-10-161-3/+128
| | | | | | | | destructors in the presence of virtual bases Reviewed at http://llvm-reviews.chandlerc.com/D1939 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192822 91177308-0d34-0410-b5e6-96231b3b80d8
* Initialize vtorDisp in class constructors and destructorsTimur Iskhodzhanov2013-10-091-7/+93
| | | | | | Reviewed at http://llvm-reviews.chandlerc.com/D1867 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192312 91177308-0d34-0410-b5e6-96231b3b80d8
* Reland 192220 "Abstract out parts of thunk emission code, add support for ↵Timur Iskhodzhanov2013-10-091-0/+8
| | | | | | simple thunks when using -cxx-abi microsoft" with relaxed assertions git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192285 91177308-0d34-0410-b5e6-96231b3b80d8
* Revert 192220 as it fails on an assertionTimur Iskhodzhanov2013-10-081-8/+0
| | | | git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192225 91177308-0d34-0410-b5e6-96231b3b80d8
* Abstract out parts of thunk emission code, add support for simple thunks ↵Timur Iskhodzhanov2013-10-081-0/+8
| | | | | | | | when using -cxx-abi microsoft Reviewed at http://llvm-reviews.chandlerc.com/D1787 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192220 91177308-0d34-0410-b5e6-96231b3b80d8
* Abstract out the emission of vtables, add basic support for vtable emission ↵Timur Iskhodzhanov2013-09-271-0/+16
| | | | | | | | when using -cxx-abi microsoft Reviewed at http://llvm-reviews.chandlerc.com/D1532 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191523 91177308-0d34-0410-b5e6-96231b3b80d8
* Abstract out virtual calls and virtual function prologue code generation; ↵Timur Iskhodzhanov2013-08-211-7/+75
| | | | | | implement them for -cxx-abi microsoft git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@188870 91177308-0d34-0410-b5e6-96231b3b80d8
* [ms-cxxabi] Move CodeGenVTables::needsVTTParameter to ItaniumCXXABI.Peter Collingbourne2013-06-281-0/+11
This function only makes sense there. Eventually it should no longer be part of the CGCXXABI interface, as it is an Itanium-specific detail. Differential Revision: http://llvm-reviews.chandlerc.com/D821 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@185213 91177308-0d34-0410-b5e6-96231b3b80d8