New user self-registration is disabled due to spam. For an account please email bugs-admin@lists.llvm.org with your e-mail address and full name.

Bug 9685 - Crash on using local struct in function template as template parameter
Summary: Crash on using local struct in function template as template parameter
Status: RESOLVED FIXED
Alias: None
Product: clang
Classification: Unclassified
Component: C++11 (show other bugs)
Version: unspecified
Hardware: All All
: P normal
Assignee: David Majnemer
URL:
Keywords: compile-fail
: 12702 15911 16669 16720 17139 17740 18219 (view as bug list)
Depends on:
Blocks:
 
Reported: 2011-04-12 06:22 PDT by jonathan.sauer
Modified: 2013-12-11 18:52 PST (History)
22 users (show)

See Also:
Fixed By Commit(s):


Attachments
The source responsible for the crash (926 bytes, application/octet-stream)
2011-04-12 06:22 PDT, jonathan.sauer
Details
Clang's crash log (8.51 KB, text/plain)
2011-04-12 06:22 PDT, jonathan.sauer
Details
Simpler repro source (311 bytes, text/x-c++src)
2011-10-14 01:27 PDT, David Blaikie
Details
Simpl (701 bytes, patch)
2011-10-30 19:42 PDT, David Blaikie
Details
Simpler repro source (701 bytes, patch)
2011-10-30 19:48 PDT, David Blaikie
Details
Run with optimised clang instead of debug clang showing clang beats gcc (1.67 KB, text/plain)
2012-10-06 20:08 PDT, Larry Evans
Details

Note You need to log in before you can comment on or make changes to this bug.
Description jonathan.sauer 2011-04-12 06:22:10 PDT
Created attachment 6436 [details]
The source responsible for the crash

The attached code crashes clang on compilation. It seems to be a weird combination of

- A class template
- A local struct in the class template's method which in turn contains a
  templated ()-operator and attributes
- An instanciation of the local struct being passed to a template method of
  another class template

I attached the crash log. Clang's version is:

$ /opt/bin/clang -v
clang version 3.0 (trunk 129269)
Target: x86_64-apple-darwin10
Thread model: posix
Comment 1 jonathan.sauer 2011-04-12 06:22:30 PDT
Created attachment 6437 [details]
Clang's crash log
Comment 2 David Blaikie 2011-10-11 23:17:18 PDT
Are you still seeing this crash? I'm getting the following with r141767 on Ubuntu:

$ clang crash.cpp
crash.cpp:11:23: warning: rvalue references are a C++0x extension [-Wc++0x-extensions]
                void forEach(Functor&& functor)
                                    ^
crash.cpp:41:14: error: 'Foo<A>::doIt()::Functor::operator()(A *)::Functor::i' is not a member of class 'Foo<A>::Functor'
                                        u->idle(i, f);
                                                ^
crash.cpp:13:4: note: in instantiation of function template specialization 'Foo<A>::doIt()::Functor::operator()<A>' requested here
                        functor(this->value);
                        ^
crash.cpp:51:11: note: in instantiation of function template specialization 'Tuple<A>::forEach<Foo<A>::Functor>' requested here
                this->t.forEach(Functor(0, 1.0f));
                        ^
crash.cpp:69:4: note: in instantiation of member function 'Foo<A>::doIt' requested here
        f.doIt();
          ^
1 warning and 1 error generated.
Comment 3 jonathan.sauer 2011-10-12 04:41:24 PDT
(In reply to comment #2)
> Are you still seeing this crash? I'm getting the following with r141767 on
> Ubuntu:

r141771 still results in the same crash here:

$ ~/LLVM/build/Release+Asserts/bin/clang -std=c++0x -v crash.cpp
clang version 3.0 (trunk 141771)
Target: x86_64-apple-darwin10.8.0
Thread model: posix
 "/Users/rynnsauer/LLVM/build/Release+Asserts/bin/clang" -cc1 -triple x86_64-apple-macosx10.6.8 -emit-obj -mrelax-all -disable-free -main-file-name crash.cpp -pic-level 1 -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 97.17 -v -resource-dir /Users/rynnsauer/LLVM/build/Release+Asserts/bin/../lib/clang/3.0 -fmodule-cache-path /var/folders/RI/RI4iqAygH0OWeTzP0+rLU++++TI/-Tmp-/clang-module-cache -std=c++0x -fdeprecated-macro -ferror-limit 19 -fmessage-length 100 -stack-protector 1 -fblocks -fobjc-dispatch-method=mixed -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -o /var/folders/RI/RI4iqAygH0OWeTzP0+rLU++++TI/-Tmp-/crash-PPnHTd.o -x c++ crash.cpp
[...]
Assertion failed: (isa<LabelDecl>(D) && "declaration not instantiated in this scope"), function findInstantiationOf, file /Users/rynnsauer/LLVM/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp, line 2303.

Strange ...
Comment 4 David Blaikie 2011-10-12 10:20:58 PDT
(In reply to comment #3)
> (In reply to comment #2)
> > Are you still seeing this crash? I'm getting the following with r141767 on
> > Ubuntu:
> 
> r141771 still results in the same crash here:

Sorry, my fault, I was using a release build. With a debug build I do see the assertion failure you're seeing. I'll look into it further & see what I can come up with.
Comment 5 David Blaikie 2011-10-14 01:27:56 PDT
Created attachment 7455 [details]
Simpler repro source

I've simplified the repro a bit - but I'm uploading it in case others have ideas about how to simplify it further. I'll play around with more simplification myself & see about fixing it soon.
Comment 6 David Blaikie 2011-10-30 19:42:51 PDT
Created attachment 7553 [details]
Simpl
Comment 7 David Blaikie 2011-10-30 19:48:00 PDT
Created attachment 7554 [details]
Simpler repro source

Further simplified the test.

The essence is any (class or function) template with a local class passed to another template that calls a member function of that local class. This will cause the member function to attempt to be instantiated in the wrong context (the local context of the function that ultimately invokes it, instead of the one it is defined in)

I have a simple 'fix' that Doug has helpfully explained is not really the right approach (& most probably broken, though I haven't created the necessary test cases to demonstrate that, though I believe they exist) though the real fix will certainly need to rework LocalInstantiationScopes substantially.

Some mechanism to track which instantiation scope a local member function corresponds to will be required. Possibly, if the class is instantiated in that scope, we can track it through that (go from the member function, to its enclosing local class and find the relevant scope there). My half-baked patch attempted to just extend the search scope, but that would be insufficient for, at the very least, multiple instances of this problem in the same scope (a function template that instantiates/calls itself with different arguments, then calls something else that uses member functions from instances of the local class from both the instantiations of the outer scope. Each one needs to find the uniquely correct outer scope, not (just) the nearest one, that has the required instantiation)
Comment 8 David Blaikie 2011-10-30 19:50:05 PDT
Oh, and one other thing just so it's written down here:

I suspect this will adversely effect lambda usage quite substantially. Most lambdas are passed to function templates (such as std::for_each, for example) & any use like that where the caller is itself a template, would probably trigger this bug. (depending on the specifics of how lambdas end up being implemented, instantiated, etc - but if they attempt to reuse local class semantics the chances are high the above will occur)
Comment 9 jonathan.sauer 2011-10-31 02:40:37 PDT
(In reply to comment #8)
> Oh, and one other thing just so it's written down here:
> 
> I suspect this will adversely effect lambda usage quite substantially. Most
> lambdas are passed to function templates (such as std::for_each, for example) &
> any use like that where the caller is itself a template, would probably trigger
> this bug. (depending on the specifics of how lambdas end up being implemented,
> instantiated, etc - but if they attempt to reuse local class semantics the
> chances are high the above will occur)

FDIS 5.1.2p3 says:
"The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non- union class type — called the closure type — whose properties are described below. This class type is not an aggregate (8.5.1). The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression."

So I think the Standard mandates that a lambda used inside a function/method is implemented as a local class.
Comment 10 David Blaikie 2012-04-30 00:48:03 PDT
*** Bug 12702 has been marked as a duplicate of this bug. ***
Comment 11 Paul Robinson 2012-07-06 17:24:29 PDT
+1, I had somebody run into this same problem the other day.
Comment 12 Larry Evans 2012-10-06 20:08:28 PDT
Created attachment 9316 [details]
Run with optimised clang instead of debug clang showing clang beats gcc
Comment 13 Larry Evans 2012-10-06 20:15:19 PDT
(In reply to comment #12)
> Created attachment 9316 [details]
> Run with optimised clang instead of debug clang showing clang beats gcc

This comment meant for previous bug, 14026.
Apparently I accidentally hit the next button and didn't notice
when I made comment #12.

Also, I added the attachment before noticing this mistake also.

Please ignore the comment and attachment.
Comment 14 Richard Smith 2012-11-19 15:22:42 PST
*** Bug 14374 has been marked as a duplicate of this bug. ***
Comment 15 Richard Smith 2012-11-19 15:22:55 PST
*** Bug 14373 has been marked as a duplicate of this bug. ***
Comment 16 Richard Smith 2012-11-19 15:26:13 PST
The problem here is that we don't instantiate local classes and their members when we instantiate a function temploid (we also have the same issue for local enumerations, but it's a bit harder to trigger the assertion there). We also have an accepts-invalid issue for the same reason. See core issue 1484, where it's clarified that everything within the braces of a function definition is instantiated with the function.
Comment 17 Richard Smith 2013-05-05 10:17:40 PDT
*** Bug 15911 has been marked as a duplicate of this bug. ***
Comment 18 Jordan Rose 2013-07-08 15:34:51 PDT
How about outside the braces? Here's some C++11 code:


#include <type_traits>

template<typename Last>
static bool isLastVoid() {
  return std::is_same<Last, void>::value;
}

template<typename First, typename... Rest>
static typename std::enable_if<sizeof...(Rest) != 0, bool>::type
isLastVoid() {
  isLastVoid<Rest...>();
}

static constexpr bool test = isLastVoid<int, void>();
Comment 19 Richard Smith 2013-07-08 16:47:25 PDT
(In reply to comment #18)
> How about outside the braces? Here's some C++11 code:

That is bug 12439, not this bug.
Comment 20 David Blaikie 2013-07-27 14:16:21 PDT
*** Bug 16720 has been marked as a duplicate of this bug. ***
Comment 21 Rob Patro 2013-08-13 23:06:50 PDT
I ran into this in some code I'm writing.  Indeed, as has been suggested earlier, it was the result of a lambda usage.  This bug, in particular, forced me to temporarily drop support for Clang and switch to GCC (which correctly handles lambdas defined in function templates being passed around) until it's fixed.
Comment 22 David Blaikie 2013-08-13 23:17:25 PDT
(In reply to comment #21)
> I ran into this in some code I'm writing.  Indeed, as has been suggested
> earlier, it was the result of a lambda usage.  This bug, in particular,
> forced me to temporarily drop support for Clang and switch to GCC (which
> correctly handles lambdas defined in function templates being passed around)
> until it's fixed.

If possible, could you provide a reduced test case? I've been going back & forth on whether lambdas are affected by this & haven't had a chance to test myself.
Comment 23 Rob Patro 2013-08-15 21:45:42 PDT
Hrmm, it looks like it's not actually lambdas that are causing it, but something else.  I reproduced a small example from the code that causes my crash and I actually narrowed it down to the use of boost::irange inside a function template that takes a class template as an argument.  If I replace the boost::irange call with a standard for loop, it compiles cleanly.  I've attached the files produced by the compiler crash.
Comment 24 Rob Patro 2013-08-15 21:51:26 PDT
(In reply to comment #23)
> Hrmm, it looks like it's not actually lambdas that are causing it, but
> something else.  I reproduced a small example from the code that causes my
> crash and I actually narrowed it down to the use of boost::irange inside a
> function template that takes a class template as an argument.  If I replace
> the boost::irange call with a standard for loop, it compiles cleanly.  I've
> attached the files produced by the compiler crash.

It looks like the generated files are too big to include.  Instead, you can find the code that causes the crash here (https://www.dropbox.com/sh/4nc339krt56rv1q/kGz3rCvJbt).  I invoked the compiler as:

clang++ -std=c++11 -stdlib=libc++ -I PATH_TO_BOOST_HEADERS -o bug main.cpp bug.cpp

which resulted in the following crash:

Assertion failed: (CastInst::castIsValid(opc, C, Ty) && "Invalid constantexpr cast!"), function getCast, file Constants.cpp, line 1449.
0  libLLVM-3.3.dylib 0x000000010449e908 llvm::sys::PrintStackTrace(__sFILE*) + 40
1  libLLVM-3.3.dylib 0x000000010449eef4 SignalHandler(int) + 548
2  libsystem_c.dylib 0x00007fff8735494a _sigtramp + 26
3  libsystem_c.dylib 0x0000000105a781f0 _sigtramp + 2121414848
4  libLLVM-3.3.dylib 0x000000010449ec26 abort + 22
5  libLLVM-3.3.dylib 0x000000010449ec01 __assert_rtn + 81
6  libLLVM-3.3.dylib 0x0000000103e9987f llvm::ConstantExpr::getCast(unsigned int, llvm::Constant*, llvm::Type*) + 511
7  clang             0x0000000102829acd llvm::IRBuilder<true, llvm::ConstantFolder, llvm::IRBuilderDefaultInserter<true> >::CreateCast(llvm::Instruction::CastOps, llvm::Value*, llvm::Type*, llvm::Twine const&) + 61
8  clang             0x000000010276da43 clang::CodeGen::CodeGenFunction::EmitCall(clang::CodeGen::CGFunctionInfo const&, llvm::Value*, clang::CodeGen::ReturnValueSlot, clang::CodeGen::CallArgList const&, clang::Decl const*, llvm::Instruction**) + 2387
9  clang             0x00000001027ab0bb clang::CodeGen::CodeGenFunction::EmitCall(clang::QualType, llvm::Value*, clang::CodeGen::ReturnValueSlot, clang::ConstExprIterator, clang::ConstExprIterator, clang::Decl const*) + 523
10 clang             0x00000001027aae39 clang::CodeGen::CodeGenFunction::EmitCallExpr(clang::CallExpr const*, clang::CodeGen::ReturnValueSlot) + 1017
11 clang             0x00000001027aff7e (anonymous namespace)::AggExprEmitter::VisitCallExpr(clang::CallExpr const*) + 110
12 clang             0x00000001027ae072 clang::StmtVisitorBase<clang::make_ptr, (anonymous namespace)::AggExprEmitter, void>::Visit(clang::Stmt*) + 2530
13 clang             0x00000001027ad5e3 clang::CodeGen::CodeGenFunction::EmitAggExpr(clang::Expr const*, clang::CodeGen::AggValueSlot) + 483
14 clang             0x000000010279d823 clang::CodeGen::CodeGenFunction::EmitAnyExpr(clang::Expr const*, clang::CodeGen::AggValueSlot, bool) + 227
15 clang             0x000000010279f3a8 EmitExprForReferenceBinding(clang::CodeGen::CodeGenFunction&, clang::Expr const*, llvm::Value*&, clang::CXXDestructorDecl const*&, clang::InitListExpr const*&, clang::QualType&, clang::NamedDecl const*) + 1624
16 clang             0x000000010279e8e6 clang::CodeGen::CodeGenFunction::EmitReferenceBindingToExpr(clang::Expr const*, clang::NamedDecl const*) + 86
17 clang             0x000000010279293c clang::CodeGen::CodeGenFunction::EmitExprAsInit(clang::Expr const*, clang::ValueDecl const*, clang::CodeGen::LValue, bool) + 124
18 clang             0x0000000102791fd0 clang::CodeGen::CodeGenFunction::EmitAutoVarInit(clang::CodeGen::CodeGenFunction::AutoVarEmission const&) + 656
19 clang             0x000000010278fe58 clang::CodeGen::CodeGenFunction::EmitVarDecl(clang::VarDecl const&) + 200
20 clang             0x000000010281f7cb clang::CodeGen::CodeGenFunction::EmitDeclStmt(clang::DeclStmt const&) + 155
21 clang             0x000000010281b362 clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*) + 162
22 clang             0x000000010281ad89 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*) + 41
23 clang             0x000000010281f159 clang::CodeGen::CodeGenFunction::EmitCXXForRangeStmt(clang::CXXForRangeStmt const&) + 281
24 clang             0x000000010281aff9 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*) + 665
25 clang             0x000000010281fe1b clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) + 91
26 clang             0x000000010282f2f9 clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) + 777
27 clang             0x0000000102838c3c clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl) + 668
28 clang             0x00000001028363d0 clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl) + 336
29 clang             0x00000001028382ed clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl) + 877
30 clang             0x000000010283a86a clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) + 234
31 clang             0x0000000102859ccf (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef) + 127
32 clang             0x000000010282b7aa clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) + 170
33 clang             0x0000000102ba0bf3 clang::Sema::InstantiateFunctionDefinition(clang::SourceLocation, clang::FunctionDecl*, bool, bool) + 1971
34 clang             0x0000000102b30ce4 clang::Sema::ActOnExplicitInstantiation(clang::Scope*, clang::SourceLocation, clang::SourceLocation, clang::Declarator&) + 4948
35 clang             0x0000000102879204 clang::Parser::ParseDeclarationAfterDeclaratorAndAttributes(clang::Declarator&, clang::Parser::ParsedTemplateInfo const&) + 116
36 clang             0x00000001028c8072 clang::Parser::ParseSingleDeclarationAfterTemplate(unsigned int, clang::Parser::ParsedTemplateInfo const&, clang::ParsingDeclRAIIObject&, clang::SourceLocation&, clang::AccessSpecifier, clang::AttributeList*) + 2594
37 clang             0x00000001028c6f2e clang::Parser::ParseExplicitInstantiation(unsigned int, clang::SourceLocation, clang::SourceLocation, clang::SourceLocation&, clang::AccessSpecifier) + 174
38 clang             0x00000001028c6dee clang::Parser::ParseDeclarationStartingWithTemplate(unsigned int, clang::SourceLocation&, clang::AccessSpecifier, clang::AttributeList*) + 206
39 clang             0x0000000102874a22 clang::Parser::ParseDeclaration(llvm::SmallVector<clang::Stmt*, 32u>&, unsigned int, clang::SourceLocation&, clang::Parser::ParsedAttributesWithRange&) + 386
40 clang             0x00000001028d1e26 clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*) + 1526
41 clang             0x00000001028d17ad clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&) + 301
42 clang             0x0000000102869cd5 clang::ParseAST(clang::Sema&, bool, bool) + 325
43 clang             0x000000010282ad55 clang::CodeGenAction::ExecuteAction() + 1205
44 clang             0x0000000102619c3c clang::FrontendAction::Execute() + 124
45 clang             0x00000001025f8b7f clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 1007
46 clang             0x00000001025caea4 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 3652
47 clang             0x00000001025c2444 cc1_main(char const**, char const**, char const*, void*) + 852
48 clang             0x00000001025c6ce4 main + 708
49 libdyld.dylib     0x00007fff807257e1 start + 0
Stack dump:
0.	Program arguments: /opt/local/libexec/llvm-3.3/bin/clang -cc1 -triple x86_64-apple-macosx10.8.0 -emit-obj -mrelax-all -disable-free -main-file-name bug.cpp -mrelocation-model pic -pic-level 2 -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 136 -resource-dir /opt/local/libexec/llvm-3.3/bin/../lib/clang/3.3 -I /opt/local/stow/boost_1_54_0_clang/include -stdlib=libc++ -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /Users/rob/ClangBug -ferror-limit 19 -fmessage-length 211 -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime=macosx-10.8.0 -fobjc-dispatch-method=mixed -fobjc-default-synthesize-properties -fencode-extended-block-signature -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -backend-option -vectorize-loops -o /var/folders/f7/6cqxgbys3_n_mp1fj3psk8g40000gn/T/bug-HVKtEZ.o -x c++ bug.cpp
1.	bug.cpp:17:76: current parser token ';'
2.	bug.cpp:9:10: LLVM IR generation of declaration 'Bug::foo'
3.	bug.cpp:9:10: Generating code for declaration 'Bug::foo'
clang: error: unable to execute command: Illegal instruction: 4
clang: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 3.3 (tags/RELEASE_33/final)
Target: x86_64-apple-darwin12.4.0
Thread model: posix
clang: note: diagnostic msg: PLEASE submit a bug report to http://llvm.org/bugs/ and include the crash backtrace, preprocessed source, and associated run script.
clang: note: diagnostic msg:
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang: note: diagnostic msg: /var/folders/f7/6cqxgbys3_n_mp1fj3psk8g40000gn/T/main-gtRJmz.cpp
clang: note: diagnostic msg: /var/folders/f7/6cqxgbys3_n_mp1fj3psk8g40000gn/T/main-gtRJmz.sh
clang: note: diagnostic msg: /var/folders/f7/6cqxgbys3_n_mp1fj3psk8g40000gn/T/bug-GbtvPa.cpp
clang: note: diagnostic msg: /var/folders/f7/6cqxgbys3_n_mp1fj3psk8g40000gn/T/bug-GbtvPa.sh
clang: note: diagnostic msg:

********************
Comment 25 Rob Patro 2013-08-20 21:59:36 PDT
Is there any idea why boost::irange may trigger a compiler crash here, but a traditional for loop works without issue?  Either way, it's sort of serious that this triggers a compiler crash; right?
Comment 26 Richard Smith 2013-09-06 19:35:16 PDT
*** Bug 17139 has been marked as a duplicate of this bug. ***
Comment 27 Richard Smith 2013-09-06 19:36:26 PDT
*** Bug 16669 has been marked as a duplicate of this bug. ***
Comment 28 David Majnemer 2013-10-22 09:23:34 PDT
*** Bug 17648 has been marked as a duplicate of this bug. ***
Comment 29 jonathan.sauer 2013-10-30 13:50:37 PDT
*** Bug 17740 has been marked as a duplicate of this bug. ***
Comment 30 David Majnemer 2013-11-21 01:42:47 PST
A fix is out for review here: http://llvm-reviews.chandlerc.com/D2236
Comment 31 David Majnemer 2013-11-27 02:23:32 PST
Fixed in r195827.
Comment 32 Richard Smith 2013-12-11 18:52:32 PST
*** Bug 18219 has been marked as a duplicate of this bug. ***