This patch fixes an assertion failure that occurs when compiling the following invalid code:
struct S { template<class T> S(T &&) {} }; template<class T> void foo1(int a0, S a1 = [](){ (void)&a0; } ) { // a0 cannot be used in the default argument for a1 } void foo2() { foo1<int>(1); }
$ clang++ -std=c++14 -c -o /dev/null test.cpp
Assertion failed: (isa<LabelDecl>(D) && "declaration not instantiated in this scope"), function findInstantiationOf, file llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp, line 2911.
The assertion fails when findInstantiationOf is called to find the instantiated decl of a0 when instantiating the lambda expression that is the default argument for a1.
To prevent the assertion failure, this patch makes CheckDefaultArgumentVisitor visit all subexpressions belonging to a default argument expression and detect local variables and parameters (that are external to the default argument) referenced in the default argument expression after the template definition is parsed. This patch also removes the diagnostic that is printed in test p7.cpp when a local variable is referenced inside a unevaluated default argument expression, which I think conforms to c++14 or later.
Also, with this patch, clang prints diagnostics when local variables or parameters are referenced inside a block expression that is used as a default argument. I wasn't 100% sure it is legal to use blocks for default arguments (I found that compiling the code below causes clang to segfault), but it seems to me that we want to handle blocks in default arguments the same way we handle lambdas.
void logRange(id i = [](){}) { } void foo1() { logRange(); }
$ clang++ -std=c++14 -c -o /dev/null -fobjc-arc test.mm
rdar://problem/33239958
There are lots of cases where we switch context in the middle of handling an expression, for instance to instantiate a template (or even *parse* a template in MSVC-compatible delayed template parsing mode). It's not reasonable to add a new form of state that all those places will need to save and restore themselves.
Please consider whether this would make sense as a member of the ExpressionEvaluationContextRecord or similar.