ahatanak created this revision.
ahatanak added a reviewer: rsmith.
ahatanak added a subscriber: cfe-commits.
I'm sending a WIP patch which fixes PR27015 to get an early feedback from the
community.
This patch attempts to fix a crash which happens when a variable template is
initialized with a generic lambda expression. Please see the example in the
email I sent to cfe-dev:
http://lists.llvm.org/pipermail/cfe-dev/2016-April/048391.html
This patch makes changes to ensure the instantiated lambda class (which is the
lambda class for fn<char> in the example) gets the right parent DeclContex
(which is Decl::TranslationUnit in the example). After applying this patch,
clang no longer crash compiling the example program. However, it still crashes
when it compiles the following code:
$ cat test0.cpp
template <class> auto fn = [] {};
template <typename> void fn1() { fn<char>; }
$ clang -std=c++14 -c -o /dev/null test0.cpp
Assertion failed: (isDependentContext() && "cannot iterate dependent
diagnostics of non-dependent context"), function ddiags, file
include/clang/AST/DependentDiagnostic.h, line 176.
...
10 clang-3.8 0x000000010b4afd18
clang::Sema::PerformDependentDiagnostics(clang::DeclContext const*,
clang::MultiLevelTemplateArgumentList const&) + 40
11 clang-3.8 0x000000010b46ee1b (anonymous
namespace)::TemplateInstantiator::transformedLocalDecl(clang::Decl*,
clang::Decl*) + 251
It fails when DeclContext::ddiags() is called on the lambda class of the old
lambda expression because it's not a dependent context.
http://reviews.llvm.org/D19175
Files:
include/clang/Sema/Sema.h
lib/Sema/SemaLambda.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Sema/TreeTransform.h
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -118,9 +118,13 @@
/// rather than in the subclass (e.g., lambda closure types).
llvm::DenseMap<Decl *, Decl *> TransformedLocalDecls;
+ /// If not null, this is the variable being initialized.
+ VarDecl *VarInit;
+
public:
/// \brief Initializes a new tree transformer.
- TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
+ TreeTransform(Sema &SemaRef, VarDecl *Var = nullptr)
+ : SemaRef(SemaRef), VarInit(Var) {}
/// \brief Retrieves a reference to the derived class.
Derived &getDerived() { return static_cast<Derived&>(*this); }
@@ -10043,11 +10047,18 @@
LSI->GLTemplateParameterList = TPL;
// Create the local class that will describe the lambda.
+ // If the new lambda is used to initialize a variable template specialization,
+ // use the old lambda's DeclContext.
+ DeclContext *DC = nullptr;
+
+ if (VarInit && isa<VarTemplateSpecializationDecl>(VarInit))
+ DC = E->getLambdaClass()->getParent();
+
CXXRecordDecl *Class
= getSema().createLambdaClosureType(E->getIntroducerRange(),
NewCallOpTSI,
/*KnownDependent=*/false,
- E->getCaptureDefault());
+ E->getCaptureDefault(), DC);
getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
// Build the call operator.
Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3898,7 +3898,7 @@
// Instantiate the initializer.
ExprResult Init =
SubstInitializer(OldVar->getInit(), TemplateArgs,
- OldVar->getInitStyle() == VarDecl::CallInit);
+ OldVar->getInitStyle() == VarDecl::CallInit, Var);
if (!Init.isInvalid()) {
bool TypeMayContainAuto = true;
Expr *InitExpr = Init.get();
Index: lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiate.cpp
+++ lib/Sema/SemaTemplateInstantiate.cpp
@@ -633,8 +633,8 @@
TemplateInstantiator(Sema &SemaRef,
const MultiLevelTemplateArgumentList &TemplateArgs,
SourceLocation Loc,
- DeclarationName Entity)
- : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
+ DeclarationName Entity, VarDecl *VarInit = nullptr)
+ : inherited(SemaRef, VarInit), TemplateArgs(TemplateArgs), Loc(Loc),
Entity(Entity) { }
/// \brief Determine whether the given type \p T has already been
@@ -2665,10 +2665,10 @@
ExprResult Sema::SubstInitializer(Expr *Init,
const MultiLevelTemplateArgumentList &TemplateArgs,
- bool CXXDirectInit) {
+ bool CXXDirectInit, VarDecl *VarInit) {
TemplateInstantiator Instantiator(*this, TemplateArgs,
SourceLocation(),
- DeclarationName());
+ DeclarationName(), VarInit);
return Instantiator.TransformInitializer(Init, CXXDirectInit);
}
Index: lib/Sema/SemaLambda.cpp
===================================================================
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -243,10 +243,14 @@
CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
TypeSourceInfo *Info,
bool KnownDependent,
- LambdaCaptureDefault CaptureDefault) {
- DeclContext *DC = CurContext;
- while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
- DC = DC->getParent();
+ LambdaCaptureDefault CaptureDefault,
+ DeclContext *DC) {
+ if (!DC) {
+ DC = CurContext;
+ while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
+ DC = DC->getParent();
+ }
+
bool IsGenericLambda = getGenericLambdaTemplateParameterList(getCurLambda(),
*this);
// Start constructing the lambda class.
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -5014,7 +5014,8 @@
CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
TypeSourceInfo *Info,
bool KnownDependent,
- LambdaCaptureDefault CaptureDefault);
+ LambdaCaptureDefault CaptureDefault,
+ DeclContext *DC = nullptr);
/// \brief Start the definition of a lambda expression.
CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class,
@@ -7095,7 +7096,7 @@
ExprResult SubstInitializer(Expr *E,
const MultiLevelTemplateArgumentList &TemplateArgs,
- bool CXXDirectInit);
+ bool CXXDirectInit, VarDecl *VarInit = nullptr);
bool
SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits