clang::Sema::ActOnFinishFunctionBody() "Leftover expressions for odr-use checking" assertion

Hi all,

During playing with clang library, I got the next assertion:
/src/oss/clang/lib/Sema/SemaDecl.cpp:10637: clang::Decl* clang::Sema::ActOnFinishFunctionBody(clang::Decl*, clang::Stmt*, bool): Assertion `MaybeODRUseExprs.empty() && "Leftover expressions for odr-use checking"' failed.

Here is backtrace:
Program received signal SIGABRT, Aborted.
0x00007fffdddef107 in __GI_raise (sig=sig@entry=6) at raise.c:56
56 raise.c: No such file or directory.
(gdb) bt
#0 0x00007fffdddef107 in __GI_raise (sig=sig@entry=6) at raise.c:56
#1 0x00007fffdddf04e8 in __GI_abort () at abort.c:89
#2 0x00007fffddde8226 in __assert_fail_base (fmt=0x7fffddf1e968 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=assertion@entry=0x7ffff679c9c0 "MaybeODRUseExprs.empty() && \"Leftover expressions for odr-use checking\"",
    file=file@entry=0x7ffff679b888 "/src/oss/clang/lib/Sema/SemaDecl.cpp", line=line@entry=10637,
    function=function@entry=0x7ffff67ac480 <clang::Sema::ActOnFinishFunctionBody(clang::Decl*, clang::Stmt*, bool)::__PRETTY_FUNCTION__> "clang::Decl* clang::Sema::ActOnFinishFunctionBody(clang::Decl*, clang::Stmt*, bool)") at assert.c:92
#3 0x00007fffddde82d2 in __GI___assert_fail (assertion=0x7ffff679c9c0 "MaybeODRUseExprs.empty() && \"Leftover expressions for odr-use checking\"", file=0x7ffff679b888 "/src/oss/clang/lib/Sema/SemaDecl.cpp", line=10637,
    function=0x7ffff67ac480 <clang::Sema::ActOnFinishFunctionBody(clang::Decl*, clang::Stmt*, bool)::__PRETTY_FUNCTION__> "clang::Decl* clang::Sema::ActOnFinishFunctionBody(clang::Decl*, clang::Stmt*, bool)") at assert.c:101
#4 0x00007ffff62062f5 in clang::Sema::ActOnFinishFunctionBody(clang::Decl*, clang::Stmt*, bool) () from /src/oss/llvm/.cmake/lib/libclangSema.so
#5 0x00007ffff6204fd9 in clang::Sema::ActOnFinishFunctionBody(clang::Decl*, clang::Stmt*) () from /src/oss/llvm/.cmake/lib/libclangSema.so
#6 0x00007ffff4dbcc52 in clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&) () from /src/oss/llvm/.cmake/lib/libclangParse.so
#7 0x00007ffff4dd65d3 in clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::LateParsedAttrList*) () from /src/oss/llvm/.cmake/lib/libclangParse.so
#8 0x00007ffff4d54446 in clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, unsigned int, clang::SourceLocation*, clang::Parser::ForRangeInit*) () from /src/oss/llvm/.cmake/lib/libclangParse.so
#9 0x00007ffff4dd58e4 in clang::Parser::ParseDeclOrFunctionDefInternal(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec&, clang::AccessSpecifier) () from /src/oss/llvm/.cmake/lib/libclangParse.so
#10 0x00007ffff4dd599c in clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*, clang::AccessSpecifier) () from /src/oss/llvm/.cmake/lib/libclangParse.so
#11 0x00007ffff4dd5102 in clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*) () from /src/oss/llvm/.cmake/lib/libclangParse.so
#12 0x00007ffff4d6beee in clang::Parser::ParseInnerNamespace(std::vector<clang::SourceLocation, std::allocator<clang::SourceLocation> >&, std::vector<clang::IdentifierInfo*, std::allocator<clang::IdentifierInfo*> >&, std::vector<clang::SourceLocation, std::allocator<clang::

>&, unsigned int, clang::SourceLocation&, clang::ParsedAttributes&, clang::BalancedDelimiterTracker&) () from /src/oss/llvm/.cmake/lib/libclangParse.so

#13 0x00007ffff4d6bd57 in clang::Parser::ParseNamespace(unsigned int, clang::SourceLocation&, clang::SourceLocation) () from /src/oss/llvm/.cmake/lib/libclangParse.so
#14 0x00007ffff4d536d2 in clang::Parser::ParseDeclaration(unsigned int, clang::SourceLocation&, clang::Parser::ParsedAttributesWithRange&) () from /src/oss/llvm/.cmake/lib/libclangParse.so
#15 0x00007ffff4dd4d8e in clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*) () from /src/oss/llvm/.cmake/lib/libclangParse.so
#16 0x00007ffff4dd468a in clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&) () from /src/oss/llvm/.cmake/lib/libclangParse.so
#17 0x00007ffff4d3ce3f in clang::ParseAST(clang::Sema&, bool, bool) () from /src/oss/llvm/.cmake/lib/libclangParse.so
#18 0x00007ffff7a8a002 in clang::ASTFrontendAction::ExecuteAction() () from /src/oss/llvm/.cmake/lib/libclangFrontend.so
#19 0x00007ffff7a89ab9 in clang::FrontendAction::Execute() () from /src/oss/llvm/.cmake/lib/libclangFrontend.so
#20 0x00007ffff7a48ca5 in clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) () from /src/oss/llvm/.cmake/lib/libclangFrontend.so
#21 0x00007ffff2d92d12 in clang::tooling::FrontendActionFactory::runInvocation(clang::CompilerInvocation*, clang::FileManager*, clang::DiagnosticConsumer*) () from /src/oss/llvm/.cmake/lib/libclangTooling.so
#22 0x00007ffff2d92bf7 in clang::tooling::ToolInvocation::runInvocation(char const*, clang::driver::Compilation*, clang::CompilerInvocation*) () from /src/oss/llvm/.cmake/lib/libclangTooling.so
#23 0x00007ffff2d92aaf in clang::tooling::ToolInvocation::run() () from /src/oss/llvm/.cmake/lib/libclangTooling.so
...

After debugging, I found the reason of a crash:
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/basic_string.h:2937:

And here is a sniplet from basic_string:
2932 inline string
2933 to_string(float __val)
2934 {
2935 const int __n =
2936 __gnu_cxx::__numeric_traits<float>::__max_exponent10 + 20;
2937 return __gnu_cxx::__to_xstring<string>(&std::vsnprintf, __n,
2938 "%f", __val);
2939 }

assert goes away if:
- you replace __n with some const (i.e. 20)
- add a cast to size_t for __n -- "(size_t)__n"

However clang compiler doesn't bail with this assert:
$ cat /tmp/string.cpp
#include <string>
int main()
{
        std::string a("a");
        a = std::to_string((float)1);
        return a.length();
};
$ clang++ -std=c++11 /tmp/string.cpp # also tested using some of the next options: "-c" "-g3" "-O0" "-O3"
$ clang++ --version
clang version 3.7.0 (http://llvm.org/git/clang.git bd12ce7a3cfb1f36c0b5e21dc7fe6a5720c8f94e) (http://llvm.org/git/llvm.git 11ef7bf0d77043e1c8d2592a819a0b247449f464)
Target: x86_64-unknown-linux-gnu
Thread model: posix

clang revision: trunk@226250
llvm revision: trunk@226269

Could anybody explain why this may differs?
And/or possible directions for debugging/patching?

Thanks in advance,
Azat.

After digging this issue for a while I finally have a patch that fixes this
issue, it passes clang regression tests (ninja check-clang) except
Frontend/source-col-map.c (but it fails before this patch too), and llvm tests
(ninja test/check).

Sure this patch must have helper function like ActOnCallExprError() or
something like this, and I will add this if the basic idea is good enough.
Therefore *I will be very appreciate if somebody from maintainers could have a
look*.
Also I'm currently working on reproducing this with 50L sample and a regression
test.

Thanks!
Azat.

Leftover-expressions-for-odr-use-checking.patch:

Please send to cfe-commits or phabricator and CC someone familiar with this code (svn blame is your friend).

Yeah, thank you for the advice.
I was going to ask here first, and after do like you write.

Here is review request:
http://reviews.llvm.org/D8458

Cheers,
Azat.