Skip to content

Commit ff1689d

Browse files
committed
[flang][OpenMP] Break up ResolveOmpObject for readability, NFC
The function ResolveOmpObject had a lot of highly-indented code in two variant visitors. Extract the visitors into their own functions, and reformat the code. Replace !(||) with !&&! in a couple of places to make the formatting a bit nicer. Use llvm::enumerate instead of manually maintaining iteration index.
1 parent da11c1d commit ff1689d

File tree

1 file changed

+176
-187
lines changed

1 file changed

+176
-187
lines changed

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 176 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,9 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
861861

862862
bool IsNestedInDirective(llvm::omp::Directive directive);
863863
void ResolveOmpObjectList(const parser::OmpObjectList &, Symbol::Flag);
864+
void ResolveOmpDesignator(
865+
const parser::Designator &designator, Symbol::Flag ompFlag);
866+
void ResolveOmpCommonBlock(const parser::Name &name, Symbol::Flag ompFlag);
864867
void ResolveOmpObject(const parser::OmpObject &, Symbol::Flag);
865868
Symbol *ResolveOmp(const parser::Name &, Symbol::Flag, Scope &);
866869
Symbol *ResolveOmp(Symbol &, Symbol::Flag, Scope &);
@@ -2683,196 +2686,182 @@ static bool SymbolOrEquivalentIsInNamelist(const Symbol &symbol) {
26832686
});
26842687
}
26852688

2686-
void OmpAttributeVisitor::ResolveOmpObject(
2687-
const parser::OmpObject &ompObject, Symbol::Flag ompFlag) {
2689+
void OmpAttributeVisitor::ResolveOmpDesignator(
2690+
const parser::Designator &designator, Symbol::Flag ompFlag) {
26882691
unsigned version{context_.langOptions().OpenMPVersion};
2689-
common::visit(
2690-
common::visitors{
2691-
[&](const parser::Designator &designator) {
2692-
if (const auto *name{
2693-
semantics::getDesignatorNameIfDataRef(designator)}) {
2694-
if (auto *symbol{ResolveOmp(*name, ompFlag, currScope())}) {
2695-
auto checkExclusivelists =
2696-
[&](const Symbol *symbol1, Symbol::Flag firstOmpFlag,
2697-
const Symbol *symbol2, Symbol::Flag secondOmpFlag) {
2698-
if ((symbol1->test(firstOmpFlag) &&
2699-
symbol2->test(secondOmpFlag)) ||
2700-
(symbol1->test(secondOmpFlag) &&
2701-
symbol2->test(firstOmpFlag))) {
2702-
context_.Say(designator.source,
2703-
"Variable '%s' may not "
2704-
"appear on both %s and %s "
2705-
"clauses on a %s construct"_err_en_US,
2706-
symbol2->name(),
2707-
Symbol::OmpFlagToClauseName(firstOmpFlag),
2708-
Symbol::OmpFlagToClauseName(secondOmpFlag),
2709-
parser::ToUpperCaseLetters(
2710-
llvm::omp::getOpenMPDirectiveName(
2711-
GetContext().directive, version)
2712-
.str()));
2713-
}
2714-
};
2715-
if (dataCopyingAttributeFlags.test(ompFlag)) {
2716-
CheckDataCopyingClause(*name, *symbol, ompFlag);
2717-
} else {
2718-
AddToContextObjectWithExplicitDSA(*symbol, ompFlag);
2719-
if (dataSharingAttributeFlags.test(ompFlag)) {
2720-
CheckMultipleAppearances(*name, *symbol, ompFlag);
2721-
}
2722-
if (privateDataSharingAttributeFlags.test(ompFlag)) {
2723-
CheckObjectIsPrivatizable(*name, *symbol, ompFlag);
2724-
}
2692+
llvm::omp::Directive directive{GetContext().directive};
27252693

2726-
if (ompFlag == Symbol::Flag::OmpAllocate) {
2727-
AddAllocateName(name);
2728-
}
2729-
}
2730-
if (ompFlag == Symbol::Flag::OmpDeclarativeAllocateDirective &&
2731-
IsAllocatable(*symbol) &&
2732-
!IsNestedInDirective(llvm::omp::Directive::OMPD_allocate)) {
2733-
context_.Say(designator.source,
2734-
"List items specified in the ALLOCATE directive must not "
2735-
"have the ALLOCATABLE attribute unless the directive is "
2736-
"associated with an ALLOCATE statement"_err_en_US);
2737-
}
2738-
if ((ompFlag == Symbol::Flag::OmpDeclarativeAllocateDirective ||
2739-
ompFlag ==
2740-
Symbol::Flag::OmpExecutableAllocateDirective) &&
2741-
ResolveOmpObjectScope(name) == nullptr) {
2742-
context_.Say(designator.source, // 2.15.3
2743-
"List items must be declared in the same scoping unit "
2744-
"in which the %s directive appears"_err_en_US,
2745-
parser::ToUpperCaseLetters(
2746-
llvm::omp::getOpenMPDirectiveName(
2747-
GetContext().directive, version)
2748-
.str()));
2749-
}
2750-
if (ompFlag == Symbol::Flag::OmpReduction) {
2751-
// Using variables inside of a namelist in OpenMP reductions
2752-
// is allowed by the standard, but is not allowed for
2753-
// privatisation. This looks like an oversight. If the
2754-
// namelist is hoisted to a global, we cannot apply the
2755-
// mapping for the reduction variable: resulting in incorrect
2756-
// results. Disabling this hoisting could make some real
2757-
// production code go slower. See discussion in #109303
2758-
if (SymbolOrEquivalentIsInNamelist(*symbol)) {
2759-
context_.Say(name->source,
2760-
"Variable '%s' in NAMELIST cannot be in a REDUCTION clause"_err_en_US,
2761-
name->ToString());
2762-
}
2763-
}
2764-
if (ompFlag == Symbol::Flag::OmpInclusiveScan ||
2765-
ompFlag == Symbol::Flag::OmpExclusiveScan) {
2766-
if (!symbol->test(Symbol::Flag::OmpInScanReduction)) {
2767-
context_.Say(name->source,
2768-
"List item %s must appear in REDUCTION clause "
2769-
"with the INSCAN modifier of the parent "
2770-
"directive"_err_en_US,
2771-
name->ToString());
2772-
}
2773-
}
2774-
if (ompFlag == Symbol::Flag::OmpDeclareTarget) {
2775-
if (symbol->IsFuncResult()) {
2776-
if (Symbol * func{currScope().symbol()}) {
2777-
CHECK(func->IsSubprogram());
2778-
func->set(ompFlag);
2779-
name->symbol = func;
2780-
}
2781-
}
2782-
}
2783-
if (GetContext().directive ==
2784-
llvm::omp::Directive::OMPD_target_data) {
2785-
checkExclusivelists(symbol, Symbol::Flag::OmpUseDevicePtr,
2786-
symbol, Symbol::Flag::OmpUseDeviceAddr);
2787-
}
2788-
if (llvm::omp::allDistributeSet.test(GetContext().directive)) {
2789-
checkExclusivelists(symbol, Symbol::Flag::OmpFirstPrivate,
2790-
symbol, Symbol::Flag::OmpLastPrivate);
2791-
}
2792-
if (llvm::omp::allTargetSet.test(GetContext().directive)) {
2793-
checkExclusivelists(symbol, Symbol::Flag::OmpIsDevicePtr,
2794-
symbol, Symbol::Flag::OmpHasDeviceAddr);
2795-
const auto *hostAssocSym{symbol};
2796-
if (!(symbol->test(Symbol::Flag::OmpIsDevicePtr) ||
2797-
symbol->test(Symbol::Flag::OmpHasDeviceAddr))) {
2798-
if (const auto *details{
2799-
symbol->detailsIf<HostAssocDetails>()}) {
2800-
hostAssocSym = &details->symbol();
2801-
}
2802-
}
2803-
Symbol::Flag dataMappingAttributeFlags[] = {
2804-
Symbol::Flag::OmpMapTo, Symbol::Flag::OmpMapFrom,
2805-
Symbol::Flag::OmpMapToFrom, Symbol::Flag::OmpMapStorage,
2806-
Symbol::Flag::OmpMapDelete, Symbol::Flag::OmpIsDevicePtr,
2807-
Symbol::Flag::OmpHasDeviceAddr};
2808-
2809-
Symbol::Flag dataSharingAttributeFlags[] = {
2810-
Symbol::Flag::OmpPrivate, Symbol::Flag::OmpFirstPrivate,
2811-
Symbol::Flag::OmpLastPrivate, Symbol::Flag::OmpShared,
2812-
Symbol::Flag::OmpLinear};
2813-
2814-
// For OMP TARGET TEAMS directive some sharing attribute
2815-
// flags and mapping attribute flags can co-exist.
2816-
if (!(llvm::omp::allTeamsSet.test(GetContext().directive) ||
2817-
llvm::omp::allParallelSet.test(
2818-
GetContext().directive))) {
2819-
for (Symbol::Flag ompFlag1 : dataMappingAttributeFlags) {
2820-
for (Symbol::Flag ompFlag2 : dataSharingAttributeFlags) {
2821-
if ((hostAssocSym->test(ompFlag2) &&
2822-
hostAssocSym->test(
2823-
Symbol::Flag::OmpExplicit)) ||
2824-
(symbol->test(ompFlag2) &&
2825-
symbol->test(Symbol::Flag::OmpExplicit))) {
2826-
checkExclusivelists(
2827-
hostAssocSym, ompFlag1, symbol, ompFlag2);
2828-
}
2829-
}
2830-
}
2831-
}
2832-
}
2833-
}
2834-
} else {
2835-
// Array sections to be changed to substrings as needed
2836-
if (AnalyzeExpr(context_, designator)) {
2837-
if (std::holds_alternative<parser::Substring>(designator.u)) {
2838-
context_.Say(designator.source,
2839-
"Substrings are not allowed on OpenMP "
2840-
"directives or clauses"_err_en_US);
2841-
}
2842-
}
2843-
// other checks, more TBD
2844-
}
2845-
},
2846-
[&](const parser::Name &name) { // common block
2847-
if (auto *symbol{ResolveOmpCommonBlockName(&name)}) {
2848-
if (!dataCopyingAttributeFlags.test(ompFlag)) {
2849-
CheckMultipleAppearances(
2850-
name, *symbol, Symbol::Flag::OmpCommonBlock);
2851-
}
2852-
// 2.15.3 When a named common block appears in a list, it has the
2853-
// same meaning as if every explicit member of the common block
2854-
// appeared in the list
2855-
auto &details{symbol->get<CommonBlockDetails>()};
2856-
unsigned index{0};
2857-
for (auto &object : details.objects()) {
2858-
if (auto *resolvedObject{
2859-
ResolveOmp(*object, ompFlag, currScope())}) {
2860-
if (dataCopyingAttributeFlags.test(ompFlag)) {
2861-
CheckDataCopyingClause(name, *resolvedObject, ompFlag);
2862-
} else {
2863-
AddToContextObjectWithExplicitDSA(*resolvedObject, ompFlag);
2864-
}
2865-
details.replace_object(*resolvedObject, index);
2866-
}
2867-
index++;
2868-
}
2869-
} else {
2870-
context_.Say(name.source, // 2.15.3
2871-
"COMMON block must be declared in the same scoping unit "
2872-
"in which the OpenMP directive or clause appears"_err_en_US);
2694+
const auto *name{semantics::getDesignatorNameIfDataRef(designator)};
2695+
if (!name) {
2696+
// Array sections to be changed to substrings as needed
2697+
if (AnalyzeExpr(context_, designator)) {
2698+
if (std::holds_alternative<parser::Substring>(designator.u)) {
2699+
context_.Say(designator.source,
2700+
"Substrings are not allowed on OpenMP directives or clauses"_err_en_US);
2701+
}
2702+
}
2703+
// other checks, more TBD
2704+
return;
2705+
}
2706+
2707+
if (auto *symbol{ResolveOmp(*name, ompFlag, currScope())}) {
2708+
auto checkExclusivelists{//
2709+
[&](const Symbol *symbol1, Symbol::Flag firstOmpFlag,
2710+
const Symbol *symbol2, Symbol::Flag secondOmpFlag) {
2711+
if ((symbol1->test(firstOmpFlag) && symbol2->test(secondOmpFlag)) ||
2712+
(symbol1->test(secondOmpFlag) && symbol2->test(firstOmpFlag))) {
2713+
context_.Say(designator.source,
2714+
"Variable '%s' may not appear on both %s and %s clauses on a %s construct"_err_en_US,
2715+
symbol2->name(), Symbol::OmpFlagToClauseName(firstOmpFlag),
2716+
Symbol::OmpFlagToClauseName(secondOmpFlag),
2717+
parser::ToUpperCaseLetters(
2718+
llvm::omp::getOpenMPDirectiveName(directive, version)));
2719+
}
2720+
}};
2721+
if (dataCopyingAttributeFlags.test(ompFlag)) {
2722+
CheckDataCopyingClause(*name, *symbol, ompFlag);
2723+
} else {
2724+
AddToContextObjectWithExplicitDSA(*symbol, ompFlag);
2725+
if (dataSharingAttributeFlags.test(ompFlag)) {
2726+
CheckMultipleAppearances(*name, *symbol, ompFlag);
2727+
}
2728+
if (privateDataSharingAttributeFlags.test(ompFlag)) {
2729+
CheckObjectIsPrivatizable(*name, *symbol, ompFlag);
2730+
}
2731+
2732+
if (ompFlag == Symbol::Flag::OmpAllocate) {
2733+
AddAllocateName(name);
2734+
}
2735+
}
2736+
if (ompFlag == Symbol::Flag::OmpDeclarativeAllocateDirective &&
2737+
IsAllocatable(*symbol) &&
2738+
!IsNestedInDirective(llvm::omp::Directive::OMPD_allocate)) {
2739+
context_.Say(designator.source,
2740+
"List items specified in the ALLOCATE directive must not have the ALLOCATABLE attribute unless the directive is associated with an ALLOCATE statement"_err_en_US);
2741+
}
2742+
if ((ompFlag == Symbol::Flag::OmpDeclarativeAllocateDirective ||
2743+
ompFlag == Symbol::Flag::OmpExecutableAllocateDirective) &&
2744+
ResolveOmpObjectScope(name) == nullptr) {
2745+
context_.Say(designator.source, // 2.15.3
2746+
"List items must be declared in the same scoping unit in which the %s directive appears"_err_en_US,
2747+
parser::ToUpperCaseLetters(
2748+
llvm::omp::getOpenMPDirectiveName(directive, version)));
2749+
}
2750+
if (ompFlag == Symbol::Flag::OmpReduction) {
2751+
// Using variables inside of a namelist in OpenMP reductions
2752+
// is allowed by the standard, but is not allowed for
2753+
// privatisation. This looks like an oversight. If the
2754+
// namelist is hoisted to a global, we cannot apply the
2755+
// mapping for the reduction variable: resulting in incorrect
2756+
// results. Disabling this hoisting could make some real
2757+
// production code go slower. See discussion in #109303
2758+
if (SymbolOrEquivalentIsInNamelist(*symbol)) {
2759+
context_.Say(name->source,
2760+
"Variable '%s' in NAMELIST cannot be in a REDUCTION clause"_err_en_US,
2761+
name->ToString());
2762+
}
2763+
}
2764+
if (ompFlag == Symbol::Flag::OmpInclusiveScan ||
2765+
ompFlag == Symbol::Flag::OmpExclusiveScan) {
2766+
if (!symbol->test(Symbol::Flag::OmpInScanReduction)) {
2767+
context_.Say(name->source,
2768+
"List item %s must appear in REDUCTION clause with the INSCAN modifier of the parent directive"_err_en_US,
2769+
name->ToString());
2770+
}
2771+
}
2772+
if (ompFlag == Symbol::Flag::OmpDeclareTarget) {
2773+
if (symbol->IsFuncResult()) {
2774+
if (Symbol * func{currScope().symbol()}) {
2775+
CHECK(func->IsSubprogram());
2776+
func->set(ompFlag);
2777+
name->symbol = func;
2778+
}
2779+
}
2780+
}
2781+
if (directive == llvm::omp::Directive::OMPD_target_data) {
2782+
checkExclusivelists(symbol, Symbol::Flag::OmpUseDevicePtr, symbol,
2783+
Symbol::Flag::OmpUseDeviceAddr);
2784+
}
2785+
if (llvm::omp::allDistributeSet.test(directive)) {
2786+
checkExclusivelists(symbol, Symbol::Flag::OmpFirstPrivate, symbol,
2787+
Symbol::Flag::OmpLastPrivate);
2788+
}
2789+
if (llvm::omp::allTargetSet.test(directive)) {
2790+
checkExclusivelists(symbol, Symbol::Flag::OmpIsDevicePtr, symbol,
2791+
Symbol::Flag::OmpHasDeviceAddr);
2792+
const auto *hostAssocSym{symbol};
2793+
if (!symbol->test(Symbol::Flag::OmpIsDevicePtr) &&
2794+
!symbol->test(Symbol::Flag::OmpHasDeviceAddr)) {
2795+
if (const auto *details{symbol->detailsIf<HostAssocDetails>()}) {
2796+
hostAssocSym = &details->symbol();
2797+
}
2798+
}
2799+
static Symbol::Flag dataMappingAttributeFlags[] = {//
2800+
Symbol::Flag::OmpMapTo, Symbol::Flag::OmpMapFrom,
2801+
Symbol::Flag::OmpMapToFrom, Symbol::Flag::OmpMapStorage,
2802+
Symbol::Flag::OmpMapDelete, Symbol::Flag::OmpIsDevicePtr,
2803+
Symbol::Flag::OmpHasDeviceAddr};
2804+
2805+
static Symbol::Flag dataSharingAttributeFlags[] = {//
2806+
Symbol::Flag::OmpPrivate, Symbol::Flag::OmpFirstPrivate,
2807+
Symbol::Flag::OmpLastPrivate, Symbol::Flag::OmpShared,
2808+
Symbol::Flag::OmpLinear};
2809+
2810+
// For OMP TARGET TEAMS directive some sharing attribute
2811+
// flags and mapping attribute flags can co-exist.
2812+
if (!llvm::omp::allTeamsSet.test(directive) &&
2813+
!llvm::omp::allParallelSet.test(directive)) {
2814+
for (Symbol::Flag ompFlag1 : dataMappingAttributeFlags) {
2815+
for (Symbol::Flag ompFlag2 : dataSharingAttributeFlags) {
2816+
if ((hostAssocSym->test(ompFlag2) &&
2817+
hostAssocSym->test(Symbol::Flag::OmpExplicit)) ||
2818+
(symbol->test(ompFlag2) &&
2819+
symbol->test(Symbol::Flag::OmpExplicit))) {
2820+
checkExclusivelists(hostAssocSym, ompFlag1, symbol, ompFlag2);
28732821
}
2874-
},
2875-
},
2822+
}
2823+
}
2824+
}
2825+
}
2826+
}
2827+
}
2828+
2829+
void OmpAttributeVisitor::ResolveOmpCommonBlock(
2830+
const parser::Name &name, Symbol::Flag ompFlag) {
2831+
if (auto *symbol{ResolveOmpCommonBlockName(&name)}) {
2832+
if (!dataCopyingAttributeFlags.test(ompFlag)) {
2833+
CheckMultipleAppearances(name, *symbol, Symbol::Flag::OmpCommonBlock);
2834+
}
2835+
// 2.15.3 When a named common block appears in a list, it has the
2836+
// same meaning as if every explicit member of the common block
2837+
// appeared in the list
2838+
auto &details{symbol->get<CommonBlockDetails>()};
2839+
for (auto [index, object] : llvm::enumerate(details.objects())) {
2840+
if (auto *resolvedObject{ResolveOmp(*object, ompFlag, currScope())}) {
2841+
if (dataCopyingAttributeFlags.test(ompFlag)) {
2842+
CheckDataCopyingClause(name, *resolvedObject, ompFlag);
2843+
} else {
2844+
AddToContextObjectWithExplicitDSA(*resolvedObject, ompFlag);
2845+
}
2846+
details.replace_object(*resolvedObject, index);
2847+
}
2848+
}
2849+
} else {
2850+
context_.Say(name.source, // 2.15.3
2851+
"COMMON block must be declared in the same scoping unit in which the OpenMP directive or clause appears"_err_en_US);
2852+
}
2853+
}
2854+
2855+
void OmpAttributeVisitor::ResolveOmpObject(
2856+
const parser::OmpObject &ompObject, Symbol::Flag ompFlag) {
2857+
common::visit(common::visitors{
2858+
[&](const parser::Designator &designator) {
2859+
ResolveOmpDesignator(designator, ompFlag);
2860+
},
2861+
[&](const parser::Name &name) { // common block
2862+
ResolveOmpCommonBlock(name, ompFlag);
2863+
},
2864+
},
28762865
ompObject.u);
28772866
}
28782867

0 commit comments

Comments
 (0)