Author: abataev Date: Wed Sep 6 07:49:58 2017 New Revision: 312638 URL: http://llvm.org/viewvc/llvm-project?rev=312638&view=rev Log: [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. Modified: cfe/trunk/include/clang/AST/DeclOpenMP.h cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/ASTDumper.cpp cfe/trunk/lib/AST/DeclPrinter.cpp cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp cfe/trunk/lib/Parse/ParseOpenMP.cpp cfe/trunk/lib/Sema/SemaOpenMP.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriterDecl.cpp cfe/trunk/test/OpenMP/declare_reduction_messages.cpp Modified: cfe/trunk/include/clang/AST/DeclOpenMP.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclOpenMP.h?rev=312638&r1=312637&r2=312638&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclOpenMP.h (original) +++ cfe/trunk/include/clang/AST/DeclOpenMP.h Wed Sep 6 07:49:58 2017 @@ -100,12 +100,22 @@ public: /// /// Here 'omp_out += omp_in' is a combiner and 'omp_priv = 0' is an initializer. class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext { +public: + enum InitKind { + CallInit, // Initialized by function call. + DirectInit, // omp_priv(<expr>) + CopyInit // omp_priv = <expr> + }; + private: friend class ASTDeclReader; /// \brief Combiner for declare reduction construct. Expr *Combiner; /// \brief Initializer for declare reduction construct. Expr *Initializer; + /// Kind of initializer - function call or omp_priv<init_expr> initializtion. + InitKind InitializerKind = CallInit; + /// \brief Reference to the previous declare reduction construct in the same /// scope with the same name. Required for proper templates instantiation if /// the declare reduction construct is declared inside compound statement. @@ -117,7 +127,8 @@ private: DeclarationName Name, QualType Ty, OMPDeclareReductionDecl *PrevDeclInScope) : ValueDecl(DK, DC, L, Name, Ty), DeclContext(DK), Combiner(nullptr), - Initializer(nullptr), PrevDeclInScope(PrevDeclInScope) {} + Initializer(nullptr), InitializerKind(CallInit), + PrevDeclInScope(PrevDeclInScope) {} void setPrevDeclInScope(OMPDeclareReductionDecl *Prev) { PrevDeclInScope = Prev; @@ -142,8 +153,13 @@ public: /// construct. Expr *getInitializer() { return Initializer; } const Expr *getInitializer() const { return Initializer; } + /// Get initializer kind. + InitKind getInitializerKind() const { return InitializerKind; } /// \brief Set initializer expression for the declare reduction construct. - void setInitializer(Expr *E) { Initializer = E; } + void setInitializer(Expr *E, InitKind IK) { + Initializer = E; + InitializerKind = IK; + } /// \brief Get reference to previous declare reduction construct in the same /// scope with the same name. Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=312638&r1=312637&r2=312638&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Wed Sep 6 07:49:58 2017 @@ -2613,6 +2613,9 @@ private: Decl *TagDecl = nullptr); /// \brief Parse 'omp declare reduction' construct. DeclGroupPtrTy ParseOpenMPDeclareReductionDirective(AccessSpecifier AS); + /// Parses initializer for provided omp_priv declaration inside the reduction + /// initializer. + void ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm); /// \brief Parses simple list of variables. /// Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=312638&r1=312637&r2=312638&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Wed Sep 6 07:49:58 2017 @@ -8588,9 +8588,11 @@ public: /// \brief Finish current declare reduction construct initializer. void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner); /// \brief Initialize declare reduction construct initializer. - void ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D); + /// \return omp_priv variable. + VarDecl *ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D); /// \brief Finish current declare reduction construct initializer. - void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer); + void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, + VarDecl *OmpPrivParm); /// \brief Called at the end of '#pragma omp declare reduction'. DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd( Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid); Modified: cfe/trunk/lib/AST/ASTDumper.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=312638&r1=312637&r2=312638&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTDumper.cpp (original) +++ cfe/trunk/lib/AST/ASTDumper.cpp Wed Sep 6 07:49:58 2017 @@ -1317,6 +1317,16 @@ void ASTDumper::VisitOMPDeclareReduction 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); } } Modified: cfe/trunk/lib/AST/DeclPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=312638&r1=312637&r2=312638&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclPrinter.cpp (original) +++ cfe/trunk/lib/AST/DeclPrinter.cpp Wed Sep 6 07:49:58 2017 @@ -1544,7 +1544,19 @@ void DeclPrinter::VisitOMPDeclareReducti 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 << ")"; } } Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=312638&r1=312637&r2=312638&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp (original) +++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp Wed Sep 6 07:49:58 2017 @@ -1200,7 +1200,14 @@ emitCombinerOrInitializer(CodeGenModule .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::emitUserDefinedRed 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); } Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=312638&r1=312637&r2=312638&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original) +++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Wed Sep 6 07:49:58 2017 @@ -341,12 +341,21 @@ Parser::ParseOpenMPDeclareReductionDirec 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::ParseOpenMPDeclareReductionDirec 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. Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=312638&r1=312637&r2=312638&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original) +++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Wed Sep 6 07:49:58 2017 @@ -11533,7 +11533,7 @@ void Sema::ActOnOpenMPDeclareReductionCo 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::ActOnOpenMPDeclareReductionIn 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::ActOnOpenMPDeclareReductionIn 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( Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=312638&r1=312637&r2=312638&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Sep 6 07:49:58 2017 @@ -2799,8 +2799,9 @@ Decl *TemplateDeclInstantiator::VisitOMP 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::VisitOMP 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; Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=312638&r1=312637&r2=312638&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Wed Sep 6 07:49:58 2017 @@ -2515,7 +2515,9 @@ void ASTDeclReader::VisitOMPDeclareReduc 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(); } Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=312638&r1=312637&r2=312638&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Wed Sep 6 07:49:58 2017 @@ -1697,6 +1697,7 @@ void ASTDeclWriter::VisitOMPDeclareReduc 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; } Modified: cfe/trunk/test/OpenMP/declare_reduction_messages.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_reduction_messages.cpp?rev=312638&r1=312637&r2=312638&view=diff ============================================================================== --- cfe/trunk/test/OpenMP/declare_reduction_messages.cpp (original) +++ cfe/trunk/test/OpenMP/declare_reduction_messages.cpp Wed Sep 6 07:49:58 2017 @@ -134,3 +134,21 @@ int main() { } return fun(15) + foo(15); // expected-note {{in instantiation of function template specialization 'foo<int>' requested here}} } + +#if __cplusplus == 201103L +struct A { + A() {} + // expected-note@+1 {{copy constructor is implicitly deleted because 'A' has a user-declared move assignment operator}} + A& operator=(A&&) = default; +}; + +int A_TEST() { + A test; +// expected-error@+1 {{call to implicitly-deleted copy constructor of 'A'}} +#pragma omp declare reduction(+ : A : omp_out) initializer(omp_priv = A()) +// expected-error@+1 {{invalid operands to binary expression ('A' and 'A')}} +#pragma omp parallel reduction(+ : test) + {} + return 0; +} +#endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits