r312638 - [OPENMP] Fix for PR34445: Reduction initializer segfaults at runtime in
Alexey Bataev via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 6 07:49:58 PDT 2017
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 at +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 at +1 {{call to implicitly-deleted copy constructor of 'A'}}
+#pragma omp declare reduction(+ : A : omp_out) initializer(omp_priv = A())
+// expected-error at +1 {{invalid operands to binary expression ('A' and 'A')}}
+#pragma omp parallel reduction(+ : test)
+ {}
+ return 0;
+}
+#endif
More information about the cfe-commits
mailing list