[OPENMP]Fix PR44133: crash on lambda reductions in templates.

Need to perform the instantiation of the combiner/initializer even if
the resulting type is not dependent, if the construct is defined in
templates in some cases.
This commit is contained in:
Alexey Bataev 2019-11-25 16:25:27 -05:00
parent 3cd9a8b7dc
commit a913e872d6
2 changed files with 94 additions and 32 deletions

View File

@ -3067,6 +3067,17 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
} else {
SubstReductionType = D->getType();
}
Expr *Combiner = D->getCombiner();
Expr *Init = D->getInitializer();
const bool CombinerRequiresInstantiation =
Combiner &&
(Combiner->isValueDependent() || Combiner->isInstantiationDependent() ||
Combiner->isTypeDependent() ||
Combiner->containsUnexpandedParameterPack());
const bool InitRequiresInstantiation =
Init &&
(Init->isValueDependent() || Init->isInstantiationDependent() ||
Init->isTypeDependent() || Init->containsUnexpandedParameterPack());
if (SubstReductionType.isNull())
return nullptr;
bool IsCorrect = !SubstReductionType.isNull();
@ -3084,11 +3095,12 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
PrevDeclInScope);
auto *NewDRD = cast<OMPDeclareReductionDecl>(DRD.get().getSingleDecl());
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDRD);
if (!RequiresInstantiation) {
if (Expr *Combiner = D->getCombiner()) {
if (!RequiresInstantiation && !CombinerRequiresInstantiation &&
!InitRequiresInstantiation) {
if (Combiner) {
NewDRD->setCombinerData(D->getCombinerIn(), D->getCombinerOut());
NewDRD->setCombiner(Combiner);
if (Expr *Init = D->getInitializer()) {
if (Init) {
NewDRD->setInitializerData(D->getInitOrig(), D->getInitPriv());
NewDRD->setInitializer(Init, D->getInitializerKind());
}
@ -3100,22 +3112,32 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
Expr *SubstCombiner = nullptr;
Expr *SubstInitializer = nullptr;
// Combiners instantiation sequence.
if (D->getCombiner()) {
SemaRef.ActOnOpenMPDeclareReductionCombinerStart(
/*S=*/nullptr, NewDRD);
SemaRef.CurrentInstantiationScope->InstantiatedLocal(
cast<DeclRefExpr>(D->getCombinerIn())->getDecl(),
cast<DeclRefExpr>(NewDRD->getCombinerIn())->getDecl());
SemaRef.CurrentInstantiationScope->InstantiatedLocal(
cast<DeclRefExpr>(D->getCombinerOut())->getDecl(),
cast<DeclRefExpr>(NewDRD->getCombinerOut())->getDecl());
auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner);
Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(),
ThisContext);
SubstCombiner = SemaRef.SubstExpr(D->getCombiner(), TemplateArgs).get();
SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner);
// Initializers instantiation sequence.
if (D->getInitializer()) {
if (Combiner) {
if (!CombinerRequiresInstantiation) {
NewDRD->setCombinerData(D->getCombinerIn(), D->getCombinerOut());
NewDRD->setCombiner(Combiner);
} else {
SemaRef.ActOnOpenMPDeclareReductionCombinerStart(
/*S=*/nullptr, NewDRD);
SemaRef.CurrentInstantiationScope->InstantiatedLocal(
cast<DeclRefExpr>(D->getCombinerIn())->getDecl(),
cast<DeclRefExpr>(NewDRD->getCombinerIn())->getDecl());
SemaRef.CurrentInstantiationScope->InstantiatedLocal(
cast<DeclRefExpr>(D->getCombinerOut())->getDecl(),
cast<DeclRefExpr>(NewDRD->getCombinerOut())->getDecl());
auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner);
Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(),
ThisContext);
SubstCombiner = SemaRef.SubstExpr(Combiner, TemplateArgs).get();
SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner);
}
}
// Initializers instantiation sequence.
if (Init) {
if (!InitRequiresInstantiation) {
NewDRD->setInitializerData(D->getInitOrig(), D->getInitPriv());
NewDRD->setInitializer(Init, D->getInitializerKind());
} else {
VarDecl *OmpPrivParm =
SemaRef.ActOnOpenMPDeclareReductionInitializerStart(
/*S=*/nullptr, NewDRD);
@ -3126,8 +3148,7 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
cast<DeclRefExpr>(D->getInitPriv())->getDecl(),
cast<DeclRefExpr>(NewDRD->getInitPriv())->getDecl());
if (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit) {
SubstInitializer =
SemaRef.SubstExpr(D->getInitializer(), TemplateArgs).get();
SubstInitializer = SemaRef.SubstExpr(Init, TemplateArgs).get();
} else {
auto *OldPrivParm =
cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl());
@ -3139,19 +3160,17 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
SemaRef.ActOnOpenMPDeclareReductionInitializerEnd(
NewDRD, SubstInitializer, OmpPrivParm);
}
IsCorrect =
IsCorrect && SubstCombiner &&
(!D->getInitializer() ||
(D->getInitializerKind() == OMPDeclareReductionDecl::CallInit &&
SubstInitializer) ||
(D->getInitializerKind() != OMPDeclareReductionDecl::CallInit &&
!SubstInitializer && !SubstInitializer));
} else {
IsCorrect = false;
}
IsCorrect = IsCorrect && (!CombinerRequiresInstantiation || SubstCombiner) &&
(!InitRequiresInstantiation ||
(!Init ||
(D->getInitializerKind() == OMPDeclareReductionDecl::CallInit &&
SubstInitializer) ||
(D->getInitializerKind() != OMPDeclareReductionDecl::CallInit &&
!SubstInitializer)));
(void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd(/*S=*/nullptr, DRD,
IsCorrect);
(void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd(
/*S=*/nullptr, DRD, IsCorrect && !D->isInvalidDecl());
return NewDRD;
}

View File

@ -0,0 +1,43 @@
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++17 -emit-llvm %s -triple x86_64-linux -fexceptions -fcxx-exceptions -o - -femit-all-decls -disable-llvm-passes | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++17 -triple x86_64-linux -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-linux -fexceptions -fcxx-exceptions -std=c++17 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-passes | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++17 -emit-llvm %s -triple x86_64-linux -fexceptions -fcxx-exceptions -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++17 -triple x86_64-linux -fexceptions -fcxx-exceptions -emit-pch -o %t %s -femit-all-decls -disable-llvm-passes
// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-linux -fexceptions -fcxx-exceptions -std=c++17 -include-pch %t -verify %s -emit-llvm -o - -femit-all-decls -disable-llvm-passes | FileCheck --check-prefix SIMD-ONLY0 %s
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
// CHECK: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @{{.+}}, i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [[STD_D:%.+]]*)* [[OUTLINED:@.+]] to void (i32*, i32*, ...)*), [[STD_D]]* %{{.+}})
// CHECK: define internal void [[OUTLINED]](i32* noalias %{{.+}}, i32* noalias %{{.+}}, [[STD_D]]* {{.+}})
// CHECK: call i32 @__kmpc_reduce_nowait(%struct.ident_t*
#ifndef HEADER
#define HEADER
typedef long unsigned a;
namespace std {
template <class> class initializer_list {
const int *b;
a c;
};
template <typename, typename> class d {};
template <typename e> class f {
public:
f(initializer_list<e>);
};
} // namespace std
template <class g, class h> void foo(g, h) {
std::d<a, double> i;
#pragma omp declare reduction(j : std::d <a, double> : []{}())
#pragma omp parallel reduction(j : i)
;
}
void k() {
std::f<int> l{};
std::f<int> m{2};
foo(l, m);
}
#endif // HEADER