|
17 | 17 | #include "clang/AST/StmtIterator.h" |
18 | 18 | #include "clang/Basic/OpenACCKinds.h" |
19 | 19 |
|
| 20 | +#include <utility> |
| 21 | + |
20 | 22 | namespace clang { |
21 | 23 | /// This is the base type for all OpenACC Clauses. |
22 | 24 | class OpenACCClause { |
@@ -75,6 +77,63 @@ class OpenACCClauseWithParams : public OpenACCClause { |
75 | 77 | } |
76 | 78 | }; |
77 | 79 |
|
| 80 | +using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>; |
| 81 | +/// A 'device_type' or 'dtype' clause, takes a list of either an 'asterisk' or |
| 82 | +/// an identifier. The 'asterisk' means 'the rest'. |
| 83 | +class OpenACCDeviceTypeClause final |
| 84 | + : public OpenACCClauseWithParams, |
| 85 | + public llvm::TrailingObjects<OpenACCDeviceTypeClause, |
| 86 | + DeviceTypeArgument> { |
| 87 | + // Data stored in trailing objects as IdentifierInfo* /SourceLocation pairs. A |
| 88 | + // nullptr IdentifierInfo* represents an asterisk. |
| 89 | + unsigned NumArchs; |
| 90 | + OpenACCDeviceTypeClause(OpenACCClauseKind K, SourceLocation BeginLoc, |
| 91 | + SourceLocation LParenLoc, |
| 92 | + ArrayRef<DeviceTypeArgument> Archs, |
| 93 | + SourceLocation EndLoc) |
| 94 | + : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc), |
| 95 | + NumArchs(Archs.size()) { |
| 96 | + assert( |
| 97 | + (K == OpenACCClauseKind::DeviceType || K == OpenACCClauseKind::DType) && |
| 98 | + "Invalid clause kind for device-type"); |
| 99 | + |
| 100 | + assert(!llvm::any_of(Archs, [](const DeviceTypeArgument &Arg) { |
| 101 | + return Arg.second.isInvalid(); |
| 102 | + }) && "Invalid SourceLocation for an argument"); |
| 103 | + |
| 104 | + assert(Archs.size() == 1 || |
| 105 | + !llvm::any_of(Archs, |
| 106 | + [](const DeviceTypeArgument &Arg) { |
| 107 | + return Arg.first == nullptr; |
| 108 | + }) && |
| 109 | + "Only a single asterisk version is permitted, and must be the " |
| 110 | + "only one"); |
| 111 | + |
| 112 | + std::uninitialized_copy(Archs.begin(), Archs.end(), |
| 113 | + getTrailingObjects<DeviceTypeArgument>()); |
| 114 | + } |
| 115 | + |
| 116 | +public: |
| 117 | + static bool classof(const OpenACCClause *C) { |
| 118 | + return C->getClauseKind() == OpenACCClauseKind::DType || |
| 119 | + C->getClauseKind() == OpenACCClauseKind::DeviceType; |
| 120 | + } |
| 121 | + bool hasAsterisk() const { |
| 122 | + return getArchitectures().size() > 0 && |
| 123 | + getArchitectures()[0].first == nullptr; |
| 124 | + } |
| 125 | + |
| 126 | + ArrayRef<DeviceTypeArgument> getArchitectures() const { |
| 127 | + return ArrayRef<DeviceTypeArgument>( |
| 128 | + getTrailingObjects<DeviceTypeArgument>(), NumArchs); |
| 129 | + } |
| 130 | + |
| 131 | + static OpenACCDeviceTypeClause * |
| 132 | + Create(const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc, |
| 133 | + SourceLocation LParenLoc, ArrayRef<DeviceTypeArgument> Archs, |
| 134 | + SourceLocation EndLoc); |
| 135 | +}; |
| 136 | + |
78 | 137 | /// A 'default' clause, has the optional 'none' or 'present' argument. |
79 | 138 | class OpenACCDefaultClause : public OpenACCClauseWithParams { |
80 | 139 | friend class ASTReaderStmt; |
|
0 commit comments