forked from OSchip/llvm-project
[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:
parent
3cd9a8b7dc
commit
a913e872d6
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue