diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2017-09-06 14:49:58 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2017-09-06 14:49:58 +0000 |
commit | 070f43aee7917f8df2b305b1f288d918dbc8e79d (patch) | |
tree | 168e77f1d8ec32be8bc28b33da309f65bff9071d /clang/lib | |
parent | 1d5a070386bab364ea34b0230707edfced7df5e9 (diff) | |
download | bcm5719-llvm-070f43aee7917f8df2b305b1f288d918dbc8e79d.tar.gz bcm5719-llvm-070f43aee7917f8df2b305b1f288d918dbc8e79d.zip |
[OPENMP] Fix for PR34445: Reduction initializer segfaults at runtime in
move constructor.
Previously user-defined reduction initializer was considered as an
assignment expression, not as initializer. Fixed this by treating the
initializer expression as an initializer.
llvm-svn: 312638
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTDumper.cpp | 10 | ||||
-rw-r--r-- | clang/lib/AST/DeclPrinter.cpp | 12 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGOpenMPRuntime.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Parse/ParseOpenMP.cpp | 85 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 19 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 32 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 1 |
8 files changed, 153 insertions, 24 deletions
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp index 7f661548780..1542f00ca75 100644 --- a/clang/lib/AST/ASTDumper.cpp +++ b/clang/lib/AST/ASTDumper.cpp @@ -1317,6 +1317,16 @@ void ASTDumper::VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D) { dumpStmt(D->getCombiner()); if (auto *Initializer = D->getInitializer()) { OS << " initializer"; + switch (D->getInitializerKind()) { + case OMPDeclareReductionDecl::DirectInit: + OS << " omp_priv = "; + break; + case OMPDeclareReductionDecl::CopyInit: + OS << " omp_priv ()"; + break; + case OMPDeclareReductionDecl::CallInit: + break; + } dumpStmt(Initializer); } } diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 00db026ebb4..68adfc7c563 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -1544,7 +1544,19 @@ void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { Out << ")"; if (auto *Init = D->getInitializer()) { Out << " initializer("; + switch (D->getInitializerKind()) { + case OMPDeclareReductionDecl::DirectInit: + Out << "omp_priv("; + break; + case OMPDeclareReductionDecl::CopyInit: + Out << "omp_priv = "; + break; + case OMPDeclareReductionDecl::CallInit: + break; + } Init->printPretty(Out, nullptr, Policy, 0); + if (D->getInitializerKind() == OMPDeclareReductionDecl::DirectInit) + Out << ")"; Out << ")"; } } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 8d055b34e79..c462b042ff5 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -1200,7 +1200,14 @@ emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, .getAddress(); }); (void)Scope.Privatize(); - CGF.EmitIgnoredExpr(CombinerInitializer); + if (!IsCombiner && Out->hasInit() && + !CGF.isTrivialInitializer(Out->getInit())) { + CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), + Out->getType().getQualifiers(), + /*IsInitializer=*/true); + } + if (CombinerInitializer) + CGF.EmitIgnoredExpr(CombinerInitializer); Scope.ForceCleanup(); CGF.FinishFunction(); return Fn; @@ -1226,7 +1233,10 @@ void CGOpenMPRuntime::emitUserDefinedReduction( Orig = &C.Idents.get("omp_orig"); } Initializer = emitCombinerOrInitializer( - CGM, D->getType(), Init, cast<VarDecl>(D->lookup(Orig).front()), + CGM, D->getType(), + D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init + : nullptr, + cast<VarDecl>(D->lookup(Orig).front()), cast<VarDecl>(D->lookup(Priv).front()), /*IsCombiner=*/false); } diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index f5638773d90..669e9aff802 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -341,12 +341,21 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope); // Parse expression. - Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), D); - InitializerResult = Actions.ActOnFinishFullExpr( - ParseAssignmentExpression().get(), D->getLocation(), - /*DiscardedValue=*/true); + VarDecl *OmpPrivParm = + Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), + D); + // Check if initializer is omp_priv <init_expr> or something else. + if (Tok.is(tok::identifier) && + Tok.getIdentifierInfo()->isStr("omp_priv")) { + ConsumeToken(); + ParseOpenMPReductionInitializerForDecl(OmpPrivParm); + } else { + InitializerResult = Actions.ActOnFinishFullExpr( + ParseAssignmentExpression().get(), D->getLocation(), + /*DiscardedValue=*/true); + } Actions.ActOnOpenMPDeclareReductionInitializerEnd( - D, InitializerResult.get()); + D, InitializerResult.get(), OmpPrivParm); if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { TPA.Commit(); @@ -370,6 +379,72 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { IsCorrect); } +void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { + // Parse declarator '=' initializer. + // If a '==' or '+=' is found, suggest a fixit to '='. + if (isTokenEqualOrEqualTypo()) { + ConsumeToken(); + + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm); + Actions.FinalizeDeclaration(OmpPrivParm); + cutOffParsing(); + return; + } + + ExprResult Init(ParseInitializer()); + + if (Init.isInvalid()) { + SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); + Actions.ActOnInitializerError(OmpPrivParm); + } else { + Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), + /*DirectInit=*/false); + } + } else if (Tok.is(tok::l_paren)) { + // Parse C++ direct initializer: '(' expression-list ')' + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + + ExprVector Exprs; + CommaLocsTy CommaLocs; + + if (ParseExpressionList(Exprs, CommaLocs, [this, OmpPrivParm, &Exprs] { + Actions.CodeCompleteConstructor( + getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(), + OmpPrivParm->getLocation(), Exprs); + })) { + Actions.ActOnInitializerError(OmpPrivParm); + SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); + } else { + // Match the ')'. + T.consumeClose(); + + assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() && + "Unexpected number of commas!"); + + ExprResult Initializer = Actions.ActOnParenListExpr( + T.getOpenLocation(), T.getCloseLocation(), Exprs); + Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(), + /*DirectInit=*/true); + } + } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { + // Parse C++0x braced-init-list. + Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); + + ExprResult Init(ParseBraceInitializer()); + + if (Init.isInvalid()) { + Actions.ActOnInitializerError(OmpPrivParm); + } else { + Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), + /*DirectInit=*/true); + } + } else { + Actions.ActOnUninitializedDecl(OmpPrivParm); + } +} + namespace { /// RAII that recreates function context for correct parsing of clauses of /// 'declare simd' construct. diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 5ba37205213..6c5433bf85e 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -11533,7 +11533,7 @@ void Sema::ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner) { DRD->setInvalidDecl(); } -void Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) { +VarDecl *Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) { auto *DRD = cast<OMPDeclareReductionDecl>(D); // Enter new function scope. @@ -11572,10 +11572,11 @@ void Sema::ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D) { DRD->addDecl(OmpPrivParm); DRD->addDecl(OmpOrigParm); } + return OmpPrivParm; } -void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, - Expr *Initializer) { +void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, + VarDecl *OmpPrivParm) { auto *DRD = cast<OMPDeclareReductionDecl>(D); DiscardCleanupsInEvaluationContext(); PopExpressionEvaluationContext(); @@ -11583,10 +11584,16 @@ void Sema::ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, PopDeclContext(); PopFunctionScopeInfo(); - if (Initializer != nullptr) - DRD->setInitializer(Initializer); - else + if (Initializer != nullptr) { + DRD->setInitializer(Initializer, OMPDeclareReductionDecl::CallInit); + } else if (OmpPrivParm->hasInit()) { + DRD->setInitializer(OmpPrivParm->getInit(), + OmpPrivParm->isDirectInit() + ? OMPDeclareReductionDecl::DirectInit + : OMPDeclareReductionDecl::CopyInit); + } else { DRD->setInvalidDecl(); + } } Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveEnd( diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 6fee23aa8bc..e702d3c7238 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2799,8 +2799,9 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl( SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner); // Initializers instantiation sequence. if (D->getInitializer()) { - SemaRef.ActOnOpenMPDeclareReductionInitializerStart( - /*S=*/nullptr, NewDRD); + VarDecl *OmpPrivParm = + SemaRef.ActOnOpenMPDeclareReductionInitializerStart( + /*S=*/nullptr, NewDRD); const char *Names[] = {"omp_orig", "omp_priv"}; for (auto &Name : Names) { DeclarationName DN(&SemaRef.Context.Idents.get(Name)); @@ -2808,17 +2809,28 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl( auto Lookup = NewDRD->lookup(DN); if (!OldLookup.empty() && !Lookup.empty()) { assert(Lookup.size() == 1 && OldLookup.size() == 1); - SemaRef.CurrentInstantiationScope->InstantiatedLocal( - OldLookup.front(), Lookup.front()); + auto *OldVD = cast<VarDecl>(OldLookup.front()); + auto *NewVD = cast<VarDecl>(Lookup.front()); + SemaRef.InstantiateVariableInitializer(NewVD, OldVD, TemplateArgs); + SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldVD, NewVD); } } - SubstInitializer = - SemaRef.SubstExpr(D->getInitializer(), TemplateArgs).get(); - SemaRef.ActOnOpenMPDeclareReductionInitializerEnd(NewDRD, - SubstInitializer); + if (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit) { + SubstInitializer = + SemaRef.SubstExpr(D->getInitializer(), TemplateArgs).get(); + } else { + IsCorrect = IsCorrect && OmpPrivParm->hasInit(); + } + SemaRef.ActOnOpenMPDeclareReductionInitializerEnd( + NewDRD, SubstInitializer, OmpPrivParm); } - IsCorrect = IsCorrect && SubstCombiner && - (!D->getInitializer() || SubstInitializer); + IsCorrect = + IsCorrect && SubstCombiner && + (!D->getInitializer() || + (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit && + SubstInitializer) || + (D->getInitializerKind() != OMPDeclareReductionDecl::CallInit && + !SubstInitializer && !SubstInitializer)); } else IsCorrect = false; diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 37cce8f507a..533a3f9bdca 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2515,7 +2515,9 @@ void ASTDeclReader::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { VisitValueDecl(D); D->setLocation(ReadSourceLocation()); D->setCombiner(Record.readExpr()); - D->setInitializer(Record.readExpr()); + D->setInitializer( + Record.readExpr(), + static_cast<OMPDeclareReductionDecl::InitKind>(Record.readInt())); D->PrevDeclInScope = ReadDeclID(); } diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index c13c528d23a..76021e270ba 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1697,6 +1697,7 @@ void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { Record.AddSourceLocation(D->getLocStart()); Record.AddStmt(D->getCombiner()); Record.AddStmt(D->getInitializer()); + Record.push_back(D->getInitializerKind()); Record.AddDeclRef(D->getPrevDeclInScope()); Code = serialization::DECL_OMP_DECLARE_REDUCTION; } |