-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[OpenMP][Flang] Fix semantic check and scoping for declare mappers #139593
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes the semantic checking for default declare mappers so that each derived type is allowed one default mapper rather than one across all derived types.
- Updated test cases in declare-mapper03.f90 to reflect the new behavior.
- Revised expected output in declare-mapper-symbols.f90 to include the derived type name prefix for default mappers.
- Refactored the default mapper symbol creation in resolve-names.cpp to generate a default name based on the derived type.
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
File | Description |
---|---|
flang/test/Semantics/OpenMP/declare-mapper03.f90 | Removed redundant type t2 and updated mapper mapping in the test for default. |
flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 | Adjusted check statements to expect the derived type name in default mapper names. |
flang/lib/Semantics/resolve-names.cpp | Refactored default symbol creation logic using a static vector for default names. |
&MakeSymbol(*mapperName, MiscDetails{MiscDetails::Kind::ConstructName}); | ||
} else { | ||
const auto &type = std::get<parser::TypeSpec>(spec.t); | ||
static llvm::SmallVector<std::string> defaultNames; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Using a static llvm::SmallVector for defaultNames may result in unexpected persistent state across invocations. Consider using a local container or clearing the vector at the beginning of the function to ensure that state does not accumulate unintentionally.
static llvm::SmallVector<std::string> defaultNames; | |
llvm::SmallVector<std::string> defaultNames; |
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see this is intentionally static
to make sure that these runtime-created strings don't get destructed while symbols are still in use, since CharBlock
doesn't own the data, but it doesn't seem to me like a very clean approach.
Not sure if perhaps adding some generic static storage for situations like this to the semantics::Scope
class, something looking similar to the allSymbols
field, would be a better idea or if there currently are any facilities to store strings not present in the original source to be used as symbols.
CC: @kiranchandramohan, @tblah.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Surely some string storage for symbol names already exists? If not then I agree that it would be better to have a utility for other situations like this. Even just wrapping the static vector in a well documented and named utility function would make it clearer what this is for.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, I encountered that even with this minor fix, some separate scoping related semantic issues would have still remained. To fix these issues altogether, I have instead taken a different approach to solving the problem.
I have changed the optional field for the mapper name to a compulsory std::string field. The parser has been updated to create a default name - "<typeSpec>.omp.default.mapper"
whenever the default name is used.
Also added a new test to flang/test/Lower/OpenMP/declare-mapper.f90 for ensuring declare mapper scoping rules apply cleanly.
@llvm/pr-subscribers-flang-parser @llvm/pr-subscribers-flang-semantics Author: Akash Banerjee (TIFitis) ChangesThe current semantic check in place is incorrect, this patch fixes this. Up to 1 'default' named mapper is allowed for each derived type. Co-authored-by: Raghu Maddhipatla <[email protected]> Full diff: https://github.com/llvm/llvm-project/pull/139593.diff 3 Files Affected:
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index b2979690f78e7..1fd0ea007319d 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -38,6 +38,7 @@
#include "flang/Semantics/type.h"
#include "flang/Support/Fortran.h"
#include "flang/Support/default-kinds.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/raw_ostream.h"
#include <list>
#include <map>
@@ -1766,14 +1767,6 @@ void OmpVisitor::ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,
// just following the natural flow, the map clauses gets processed before
// the type has been fully processed.
BeginDeclTypeSpec();
- if (auto &mapperName{std::get<std::optional<parser::Name>>(spec.t)}) {
- mapperName->symbol =
- &MakeSymbol(*mapperName, MiscDetails{MiscDetails::Kind::ConstructName});
- } else {
- const parser::CharBlock defaultName{"default", 7};
- MakeSymbol(
- defaultName, Attrs{}, MiscDetails{MiscDetails::Kind::ConstructName});
- }
PushScope(Scope::Kind::OtherConstruct, nullptr);
Walk(std::get<parser::TypeSpec>(spec.t));
@@ -1783,6 +1776,18 @@ void OmpVisitor::ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,
Walk(clauses);
EndDeclTypeSpec();
PopScope();
+
+ if (auto &mapperName{std::get<std::optional<parser::Name>>(spec.t)}) {
+ mapperName->symbol =
+ &MakeSymbol(*mapperName, MiscDetails{MiscDetails::Kind::ConstructName});
+ } else {
+ const auto &type = std::get<parser::TypeSpec>(spec.t);
+ static llvm::SmallVector<std::string> defaultNames;
+ defaultNames.emplace_back(
+ type.declTypeSpec->derivedTypeSpec().name().ToString() + ".default");
+ MakeSymbol(defaultNames.back(), Attrs{},
+ MiscDetails{MiscDetails::Kind::ConstructName});
+ }
}
void OmpVisitor::ProcessReductionSpecifier(
diff --git a/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 b/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90
index b4e03bd1632e5..0dda5b4456987 100644
--- a/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90
+++ b/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90
@@ -2,23 +2,23 @@
program main
!CHECK-LABEL: MainProgram scope: main
- implicit none
+ implicit none
- type ty
- integer :: x
- end type ty
- !$omp declare mapper(mymapper : ty :: mapped) map(mapped, mapped%x)
- !$omp declare mapper(ty :: maptwo) map(maptwo, maptwo%x)
+ type ty
+ integer :: x
+ end type ty
+ !$omp declare mapper(mymapper : ty :: mapped) map(mapped, mapped%x)
+ !$omp declare mapper(ty :: maptwo) map(maptwo, maptwo%x)
!! Note, symbols come out in their respective scope, but not in declaration order.
-!CHECK: default: Misc ConstructName
!CHECK: mymapper: Misc ConstructName
!CHECK: ty: DerivedType components: x
+!CHECK: ty.default: Misc ConstructName
!CHECK: DerivedType scope: ty
!CHECK: OtherConstruct scope:
!CHECK: mapped (OmpMapToFrom) {{.*}} ObjectEntity type: TYPE(ty)
-!CHECK: OtherConstruct scope:
+!CHECK: OtherConstruct scope:
!CHECK: maptwo (OmpMapToFrom) {{.*}} ObjectEntity type: TYPE(ty)
-
+
end program main
diff --git a/flang/test/Semantics/OpenMP/declare-mapper03.f90 b/flang/test/Semantics/OpenMP/declare-mapper03.f90
index b70b8a67f33e0..84fc3efafb3ad 100644
--- a/flang/test/Semantics/OpenMP/declare-mapper03.f90
+++ b/flang/test/Semantics/OpenMP/declare-mapper03.f90
@@ -5,12 +5,8 @@
integer :: y
end type t1
-type :: t2
- real :: y, z
-end type t2
-
!error: 'default' is already declared in this scoping unit
!$omp declare mapper(t1::x) map(x, x%y)
-!$omp declare mapper(t2::w) map(w, w%y, w%z)
+!$omp declare mapper(t1::x) map(x)
end
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you Akash! I have just one comment and minor nits.
&MakeSymbol(*mapperName, MiscDetails{MiscDetails::Kind::ConstructName}); | ||
} else { | ||
const auto &type = std::get<parser::TypeSpec>(spec.t); | ||
static llvm::SmallVector<std::string> defaultNames; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see this is intentionally static
to make sure that these runtime-created strings don't get destructed while symbols are still in use, since CharBlock
doesn't own the data, but it doesn't seem to me like a very clean approach.
Not sure if perhaps adding some generic static storage for situations like this to the semantics::Scope
class, something looking similar to the allSymbols
field, would be a better idea or if there currently are any facilities to store strings not present in the original source to be used as symbols.
CC: @kiranchandramohan, @tblah.
MakeSymbol(defaultNames.back(), Attrs{}, | ||
MiscDetails{MiscDetails::Kind::ConstructName}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: There's already an attribute-less overload of that function.
MakeSymbol(defaultNames.back(), Attrs{}, | |
MiscDetails{MiscDetails::Kind::ConstructName}); | |
MakeSymbol(defaultNames.back(), MiscDetails{MiscDetails::Kind::ConstructName}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, the attribute-less overload uses a different type for the name parameter and thus can't be used directly. Passing a default Attrs{} seems likely a cleaner solution than changing the name to the correct type so I have went with this approach for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes the semantic check for default declare mappers so that each derived type may have its own default mapper rather than a single default across all types. The key changes are a renaming of the default mapper identifier from ".default" to ".omp.default.mapper", conversion of mapper names from an optional Name to a string for clarity, and corresponding updates across tests, parsing, semantic resolution, and lowering.
Reviewed Changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.
Show a summary per file
File | Description |
---|---|
flang/test/Semantics/OpenMP/declare-mapper03.f90 | Removed unused type and updated mapper declaration to match new naming |
flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 | Updated expected symbol names for default mappers in tests |
flang/test/Parser/OpenMP/metadirective-dirspec.f90 | Adjusted parse-tree output from using Name to string for mapper names |
flang/test/Parser/OpenMP/declare-mapper-unparse.f90 | Modified unparsed mapper names from Name to string output |
flang/test/Lower/OpenMP/map-mapper.f90 | Updated CHECK-LABEL and CHECK lines for altered default mapper naming |
flang/test/Lower/OpenMP/declare-mapper.f90 | Added new test file and updated mapper name references in checks |
flang/lib/Semantics/resolve-names.cpp | Changed mapper name processing to use string-based names |
flang/lib/Parser/unparse.cpp | Updated mapper name extraction and printing logic for new syntax |
flang/lib/Parser/openmp-parsers.cpp | Added a helper to construct an OmpMapperSpecifier using string names |
flang/lib/Lower/OpenMP/OpenMP.cpp | Adjusted mapper identifier construction to use new naming convention |
flang/lib/Lower/OpenMP/ClauseProcessor.cpp | Updated mapper name handling to match new default syntax |
flang/include/flang/Parser/parse-tree.h | Changed the OmpMapperSpecifier tuple field from an optional Name to a string |
std::optional<Name> &&mapperName, TypeSpec &&typeSpec, Name &&varName) { | ||
// If a name is present, parse: name ":" typeSpec "::" name | ||
// This matches the syntax: <mapper-name> : <type-spec> :: <variable-name> | ||
if (mapperName.has_value() && mapperName->ToString() != "default") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function ConstructOmpMapperSpecifier continues to accept a std::optional for the mapper name while the parse tree now uses a std::string. Consider aligning the interface to accept a std::string (or handle an empty string) for consistency.
Copilot uses AI. Check for mistakes.
@@ -3540,7 +3540,7 @@ WRAPPER_CLASS(OmpLocatorList, std::list<OmpLocator>); | |||
struct OmpMapperSpecifier { | |||
// Absent mapper-identifier is equivalent to DEFAULT. | |||
TUPLE_CLASS_BOILERPLATE(OmpMapperSpecifier); | |||
std::tuple<std::optional<Name>, TypeSpec, Name> t; | |||
std::tuple<std::string, TypeSpec, Name> t; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Given the change from std::optional to std::string for mapper names, adding a comment to explain the rationale for this decision would improve clarity and help maintain consistency across the codebase.
Copilot uses AI. Check for mistakes.
Moved PR to #140560 to create a PR stack. |
The current semantic check in place is incorrect, this patch fixes this.
Up to 1 'default' named mapper should be allowed for each derived type.
The current semantic check only allows up to 1 'default' named mapper across all derived types.
This also makes sure that declare mappers follow proper scoping rules for both default and named mappers.
Co-authored-by: Raghu Maddhipatla [email protected]