@@ -91,11 +91,12 @@ template <typename T> class DirectiveAttributeVisitor {
91
91
void SetContextAssociatedLoopLevel (std::int64_t level) {
92
92
GetContext ().associatedLoopLevel = level;
93
93
}
94
- Symbol &MakeAssocSymbol (const SourceName &name, Symbol &prev, Scope &scope) {
94
+ Symbol &MakeAssocSymbol (
95
+ const SourceName &name, const Symbol &prev, Scope &scope) {
95
96
const auto pair{scope.try_emplace (name, Attrs{}, HostAssocDetails{prev})};
96
97
return *pair.first ->second ;
97
98
}
98
- Symbol &MakeAssocSymbol (const SourceName &name, Symbol &prev) {
99
+ Symbol &MakeAssocSymbol (const SourceName &name, const Symbol &prev) {
99
100
return MakeAssocSymbol (name, prev, currScope ());
100
101
}
101
102
void AddDataSharingAttributeObject (SymbolRef object) {
@@ -108,6 +109,7 @@ template <typename T> class DirectiveAttributeVisitor {
108
109
const parser::Name *GetLoopIndex (const parser::DoConstruct &);
109
110
const parser::DoConstruct *GetDoConstructIf (
110
111
const parser::ExecutionPartConstruct &);
112
+ Symbol *DeclareNewPrivateAccessEntity (const Symbol &, Symbol::Flag, Scope &);
111
113
Symbol *DeclarePrivateAccessEntity (
112
114
const parser::Name &, Symbol::Flag, Scope &);
113
115
Symbol *DeclarePrivateAccessEntity (Symbol &, Symbol::Flag, Scope &);
@@ -771,6 +773,19 @@ const parser::DoConstruct *DirectiveAttributeVisitor<T>::GetDoConstructIf(
771
773
return parser::Unwrap<parser::DoConstruct>(x);
772
774
}
773
775
776
+ template <typename T>
777
+ Symbol *DirectiveAttributeVisitor<T>::DeclareNewPrivateAccessEntity(
778
+ const Symbol &object, Symbol::Flag flag, Scope &scope) {
779
+ assert (object.owner () != currScope ());
780
+ auto &symbol{MakeAssocSymbol (object.name (), object, scope)};
781
+ symbol.set (flag);
782
+ if (flag == Symbol::Flag::OmpCopyIn) {
783
+ // The symbol in copyin clause must be threadprivate entity.
784
+ symbol.set (Symbol::Flag::OmpThreadprivate);
785
+ }
786
+ return &symbol;
787
+ }
788
+
774
789
template <typename T>
775
790
Symbol *DirectiveAttributeVisitor<T>::DeclarePrivateAccessEntity(
776
791
const parser::Name &name, Symbol::Flag flag, Scope &scope) {
@@ -785,13 +800,7 @@ template <typename T>
785
800
Symbol *DirectiveAttributeVisitor<T>::DeclarePrivateAccessEntity(
786
801
Symbol &object, Symbol::Flag flag, Scope &scope) {
787
802
if (object.owner () != currScope ()) {
788
- auto &symbol{MakeAssocSymbol (object.name (), object, scope)};
789
- symbol.set (flag);
790
- if (flag == Symbol::Flag::OmpCopyIn) {
791
- // The symbol in copyin clause must be threadprivate entity.
792
- symbol.set (Symbol::Flag::OmpThreadprivate);
793
- }
794
- return &symbol;
803
+ return DeclareNewPrivateAccessEntity (object, flag, scope);
795
804
} else {
796
805
object.set (flag);
797
806
return &object;
@@ -2075,13 +2084,30 @@ void OmpAttributeVisitor::Post(const parser::Name &name) {
2075
2084
if (found->test (semantics::Symbol::Flag::OmpThreadprivate))
2076
2085
return ;
2077
2086
}
2078
- if (!IsPrivatizable (symbol)) {
2087
+
2088
+ std::set<const Symbol *> stmtFunctionSymbols;
2089
+ if (auto *stmtFunction{symbol->detailsIf <semantics::SubprogramDetails>()};
2090
+ stmtFunction && stmtFunction->stmtFunction ()) {
2091
+ // Each non-dummy argument from a statement function must be handled too,
2092
+ // as if it was explicitly referenced.
2093
+ semantics::UnorderedSymbolSet symbols{
2094
+ CollectSymbols (stmtFunction->stmtFunction ().value ())};
2095
+ for (const auto &sym : symbols) {
2096
+ if (!IsStmtFunctionDummy (sym) && IsPrivatizable (&*sym) &&
2097
+ !IsObjectWithDSA (*sym)) {
2098
+ stmtFunctionSymbols.insert (&*sym);
2099
+ }
2100
+ }
2101
+ if (stmtFunctionSymbols.empty ()) {
2102
+ return ;
2103
+ }
2104
+ } else if (!IsPrivatizable (symbol)) {
2079
2105
return ;
2080
2106
}
2081
2107
2082
2108
// Implicitly determined DSAs
2083
2109
// OMP 5.2 5.1.1 - Variables Referenced in a Construct
2084
- Symbol *lastDeclSymbol = nullptr ;
2110
+ std::vector< const Symbol *> lastDeclSymbols ;
2085
2111
std::optional<Symbol::Flag> prevDSA;
2086
2112
for (int dirDepth{0 }; dirDepth < (int )dirContext_.size (); ++dirDepth) {
2087
2113
DirContext &dirContext = dirContext_[dirDepth];
@@ -2126,23 +2152,59 @@ void OmpAttributeVisitor::Post(const parser::Name &name) {
2126
2152
// it would have the private flag set.
2127
2153
// This would make x appear to be defined in p2, causing it to be
2128
2154
// privatized in p2 and its privatization in p1 to be skipped.
2129
- auto makePrivateSymbol = [&](Symbol::Flag flag) {
2130
- Symbol *hostSymbol =
2131
- lastDeclSymbol ? lastDeclSymbol : &symbol->GetUltimate ();
2132
- lastDeclSymbol = DeclarePrivateAccessEntity (
2133
- *hostSymbol, flag, context_.FindScope (dirContext.directiveSource ));
2134
- return lastDeclSymbol;
2155
+ // TODO Move the lambda functions below to a separate class.
2156
+ auto hostSymbol = [&](const Symbol *sym, int index = 0 ) {
2157
+ if (lastDeclSymbols.empty ())
2158
+ return &sym->GetUltimate ();
2159
+ return lastDeclSymbols[index];
2160
+ };
2161
+ auto declNewPrivateSymbol = [&](const Symbol *sym, Symbol::Flag flag,
2162
+ bool implicit) {
2163
+ Symbol *newSym = DeclareNewPrivateAccessEntity (
2164
+ *sym, flag, context_.FindScope (dirContext.directiveSource ));
2165
+ if (implicit)
2166
+ newSym->set (Symbol::Flag::OmpImplicit);
2167
+ return newSym;
2168
+ };
2169
+ auto makePrivateSymbol = [&](Symbol::Flag flag, bool implicit = false ) {
2170
+ bool hasLastDeclSymbols = !lastDeclSymbols.empty ();
2171
+ auto updateLastDeclSymbols = [&](const Symbol *sym, int index = 0 ) {
2172
+ if (hasLastDeclSymbols)
2173
+ lastDeclSymbols[index] = sym;
2174
+ else
2175
+ lastDeclSymbols.push_back (sym);
2176
+ };
2177
+
2178
+ if (stmtFunctionSymbols.empty ()) {
2179
+ const Symbol *newSym =
2180
+ declNewPrivateSymbol (hostSymbol (symbol), flag, implicit);
2181
+ updateLastDeclSymbols (newSym);
2182
+ return ;
2183
+ }
2184
+
2185
+ int i = 0 ;
2186
+ for (const auto *sym : stmtFunctionSymbols) {
2187
+ Symbol *newSym =
2188
+ declNewPrivateSymbol (hostSymbol (sym, i), flag, implicit);
2189
+ newSym->set (Symbol::Flag::OmpFromStmtFunction);
2190
+ updateLastDeclSymbols (newSym, i++);
2191
+ }
2135
2192
};
2136
2193
auto makeSharedSymbol = [&]() {
2137
- Symbol *hostSymbol =
2138
- lastDeclSymbol ? lastDeclSymbol : &symbol->GetUltimate ();
2139
- MakeAssocSymbol (symbol->name (), *hostSymbol,
2140
- context_.FindScope (dirContext.directiveSource ));
2194
+ if (stmtFunctionSymbols.empty ()) {
2195
+ MakeAssocSymbol (symbol->name (), *hostSymbol (symbol),
2196
+ context_.FindScope (dirContext.directiveSource ));
2197
+ } else {
2198
+ int i = 0 ;
2199
+ for (const auto *sym : stmtFunctionSymbols) {
2200
+ MakeAssocSymbol (sym->name (), *hostSymbol (sym, i++),
2201
+ context_.FindScope (dirContext.directiveSource ));
2202
+ }
2203
+ }
2141
2204
};
2142
2205
auto useLastDeclSymbol = [&]() {
2143
- if (lastDeclSymbol)
2144
- MakeAssocSymbol (symbol->name (), *lastDeclSymbol,
2145
- context_.FindScope (dirContext.directiveSource ));
2206
+ if (!lastDeclSymbols.empty ())
2207
+ makeSharedSymbol ();
2146
2208
};
2147
2209
2148
2210
bool taskGenDir = llvm::omp::taskGeneratingSet.test (dirContext.directive );
@@ -2190,7 +2252,7 @@ void OmpAttributeVisitor::Post(const parser::Name &name) {
2190
2252
} else {
2191
2253
// 7) firstprivate
2192
2254
dsa = Symbol::Flag::OmpFirstPrivate;
2193
- makePrivateSymbol (*dsa)-> set (Symbol::Flag::OmpImplicit );
2255
+ makePrivateSymbol (*dsa, /* implicit= */ true );
2194
2256
}
2195
2257
}
2196
2258
prevDSA = dsa;
0 commit comments