File tree Expand file tree Collapse file tree 4 files changed +41
-5
lines changed Expand file tree Collapse file tree 4 files changed +41
-5
lines changed Original file line number Diff line number Diff line change @@ -1227,18 +1227,24 @@ bool CheckForCoindexedObject(parser::ContextualMessages &,
1227
1227
const std::optional<ActualArgument> &, const std::string &procName,
1228
1228
const std::string &argName);
1229
1229
1230
- // / Check if any of the symbols part of the expression has a cuda data
1231
- // / attribute.
1232
- inline bool HasCUDAAttrs ( const Expr<SomeType> &expr) {
1230
+ // Get the number of distinct symbols with CUDA attribute in the expression.
1231
+ template < typename A> inline int GetNbOfCUDASymbols ( const A &expr) {
1232
+ semantics::UnorderedSymbolSet symbols;
1233
1233
for (const Symbol &sym : CollectSymbols (expr)) {
1234
1234
if (const auto *details =
1235
1235
sym.GetUltimate ().detailsIf <semantics::ObjectEntityDetails>()) {
1236
1236
if (details->cudaDataAttr ()) {
1237
- return true ;
1237
+ symbols. insert (sym) ;
1238
1238
}
1239
1239
}
1240
1240
}
1241
- return false ;
1241
+ return symbols.size ();
1242
+ }
1243
+
1244
+ // Check if any of the symbols part of the expression has a CUDA data
1245
+ // attribute.
1246
+ template <typename A> inline bool HasCUDAAttrs (const A &expr) {
1247
+ return GetNbOfCUDASymbols (expr) > 0 ;
1242
1248
}
1243
1249
1244
1250
// / Check if the expression is a mix of host and device variables that require
Original file line number Diff line number Diff line change 9
9
#include " check-cuda.h"
10
10
#include " flang/Common/template.h"
11
11
#include " flang/Evaluate/fold.h"
12
+ #include " flang/Evaluate/tools.h"
12
13
#include " flang/Evaluate/traverse.h"
13
14
#include " flang/Parser/parse-tree-visitor.h"
14
15
#include " flang/Parser/parse-tree.h"
15
16
#include " flang/Parser/tools.h"
16
17
#include " flang/Semantics/expression.h"
17
18
#include " flang/Semantics/symbol.h"
19
+ #include " flang/Semantics/tools.h"
18
20
19
21
// Once labeled DO constructs have been canonicalized and their parse subtrees
20
22
// transformed into parser::DoConstructs, scan the parser::Blocks of the program
@@ -413,4 +415,18 @@ void CUDAChecker::Enter(const parser::CUFKernelDoConstruct &x) {
413
415
}
414
416
}
415
417
418
+ void CUDAChecker::Enter (const parser::AssignmentStmt &x) {
419
+ const evaluate::Assignment *assign{semantics::GetAssignment (x)};
420
+ int nbLhs{evaluate::GetNbOfCUDASymbols (assign->lhs )};
421
+ int nbRhs{evaluate::GetNbOfCUDASymbols (assign->rhs )};
422
+ auto lhsLoc{std::get<parser::Variable>(x.t ).GetSource ()};
423
+
424
+ // device to host transfer with more than one device object on the rhs is not
425
+ // legal.
426
+ if (nbLhs == 0 && nbRhs > 1 ) {
427
+ context_.Say (lhsLoc,
428
+ " More than one reference to a CUDA object on the right hand side of the assigment" _err_en_US);
429
+ }
430
+ }
431
+
416
432
} // namespace Fortran::semantics
Original file line number Diff line number Diff line change @@ -17,6 +17,7 @@ struct Program;
17
17
class Messages ;
18
18
struct Name ;
19
19
class CharBlock ;
20
+ struct AssignmentStmt ;
20
21
struct ExecutionPartConstruct ;
21
22
struct ExecutableConstruct ;
22
23
struct ActionStmt ;
@@ -38,6 +39,7 @@ class CUDAChecker : public virtual BaseChecker {
38
39
void Enter (const parser::FunctionSubprogram &);
39
40
void Enter (const parser::SeparateModuleSubprogram &);
40
41
void Enter (const parser::CUFKernelDoConstruct &);
42
+ void Enter (const parser::AssignmentStmt &);
41
43
42
44
private:
43
45
SemanticsContext &context_;
Original file line number Diff line number Diff line change
1
+ ! RUN: %python %S/test_errors.py %s %flang_fc1
2
+
3
+ subroutine sub1()
4
+ real, device :: adev(10), bdev(10)
5
+ real :: ahost(10)
6
+
7
+ !ERROR: More than one reference to a CUDA object on the right hand side of the assigment
8
+ ahost = adev + bdev
9
+
10
+ ahost = adev + adev
11
+
12
+ end subroutine
You can’t perform that action at this time.
0 commit comments