[OPENMP50]Add support for extended device clause in target directives.

Added parsing/sema/serialization support for extended device clause in
executable target directives.
This commit is contained in:
Alexey Bataev 2020-03-18 15:01:15 -04:00
parent 1010c44b4c
commit 2f8894a5b8
19 changed files with 168 additions and 50 deletions

View File

@ -4433,6 +4433,12 @@ class OMPDeviceClause : public OMPClause, public OMPClauseWithPreInit {
/// Location of '('. /// Location of '('.
SourceLocation LParenLoc; SourceLocation LParenLoc;
/// Device clause modifier.
OpenMPDeviceClauseModifier Modifier = OMPC_DEVICE_unknown;
/// Location of the modifier.
SourceLocation ModifierLoc;
/// Device number. /// Device number.
Stmt *Device = nullptr; Stmt *Device = nullptr;
@ -4441,20 +4447,30 @@ class OMPDeviceClause : public OMPClause, public OMPClauseWithPreInit {
/// \param E Device number. /// \param E Device number.
void setDevice(Expr *E) { Device = E; } void setDevice(Expr *E) { Device = E; }
/// Sets modifier.
void setModifier(OpenMPDeviceClauseModifier M) { Modifier = M; }
/// Setst modifier location.
void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; }
public: public:
/// Build 'device' clause. /// Build 'device' clause.
/// ///
/// \param Modifier Clause modifier.
/// \param E Expression associated with this clause. /// \param E Expression associated with this clause.
/// \param CaptureRegion Innermost OpenMP region where expressions in this /// \param CaptureRegion Innermost OpenMP region where expressions in this
/// clause must be captured. /// clause must be captured.
/// \param StartLoc Starting location of the clause. /// \param StartLoc Starting location of the clause.
/// \param ModifierLoc Modifier location.
/// \param LParenLoc Location of '('. /// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause. /// \param EndLoc Ending location of the clause.
OMPDeviceClause(Expr *E, Stmt *HelperE, OpenMPDirectiveKind CaptureRegion, OMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *E, Stmt *HelperE,
SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation ModifierLoc,
SourceLocation EndLoc) SourceLocation EndLoc)
: OMPClause(OMPC_device, StartLoc, EndLoc), OMPClauseWithPreInit(this), : OMPClause(OMPC_device, StartLoc, EndLoc), OMPClauseWithPreInit(this),
LParenLoc(LParenLoc), Device(E) { LParenLoc(LParenLoc), Modifier(Modifier), ModifierLoc(ModifierLoc),
Device(E) {
setPreInitStmt(HelperE, CaptureRegion); setPreInitStmt(HelperE, CaptureRegion);
} }
@ -4475,6 +4491,12 @@ public:
/// Return device number. /// Return device number.
Expr *getDevice() const { return cast<Expr>(Device); } Expr *getDevice() const { return cast<Expr>(Device); }
/// Gets modifier.
OpenMPDeviceClauseModifier getModifier() const { return Modifier; }
/// Gets modifier location.
SourceLocation getModifierLoc() const { return ModifierLoc; }
child_range children() { return child_range(&Device, &Device + 1); } child_range children() { return child_range(&Device, &Device + 1); }
const_child_range children() const { const_child_range children() const {

View File

@ -212,6 +212,9 @@
#ifndef OPENMP_DEPOBJ_CLAUSE #ifndef OPENMP_DEPOBJ_CLAUSE
#define OPENMP_DEPOBJ_CLAUSE(Name) #define OPENMP_DEPOBJ_CLAUSE(Name)
#endif #endif
#ifndef OPENMP_DEVICE_MODIFIER
#define OPENMP_DEVICE_MODIFIER(Name)
#endif
// OpenMP clauses. // OpenMP clauses.
OPENMP_CLAUSE(allocator, OMPAllocatorClause) OPENMP_CLAUSE(allocator, OMPAllocatorClause)
@ -366,6 +369,10 @@ OPENMP_SCHEDULE_MODIFIER(monotonic)
OPENMP_SCHEDULE_MODIFIER(nonmonotonic) OPENMP_SCHEDULE_MODIFIER(nonmonotonic)
OPENMP_SCHEDULE_MODIFIER(simd) OPENMP_SCHEDULE_MODIFIER(simd)
// Modifiers for 'device' clause.
OPENMP_DEVICE_MODIFIER(ancestor)
OPENMP_DEVICE_MODIFIER(device_num)
// Static attributes for 'defaultmap' clause. // Static attributes for 'defaultmap' clause.
OPENMP_DEFAULTMAP_KIND(scalar) OPENMP_DEFAULTMAP_KIND(scalar)
OPENMP_DEFAULTMAP_KIND(aggregate) OPENMP_DEFAULTMAP_KIND(aggregate)
@ -1091,6 +1098,7 @@ OPENMP_DEPOBJ_CLAUSE(depend)
OPENMP_DEPOBJ_CLAUSE(destroy) OPENMP_DEPOBJ_CLAUSE(destroy)
OPENMP_DEPOBJ_CLAUSE(update) OPENMP_DEPOBJ_CLAUSE(update)
#undef OPENMP_DEVICE_MODIFIER
#undef OPENMP_DEPOBJ_CLAUSE #undef OPENMP_DEPOBJ_CLAUSE
#undef OPENMP_FLUSH_CLAUSE #undef OPENMP_FLUSH_CLAUSE
#undef OPENMP_ORDER_KIND #undef OPENMP_ORDER_KIND

View File

@ -51,6 +51,13 @@ enum OpenMPScheduleClauseModifier {
OMPC_SCHEDULE_MODIFIER_last OMPC_SCHEDULE_MODIFIER_last
}; };
/// OpenMP modifiers for 'device' clause.
enum OpenMPDeviceClauseModifier {
#define OPENMP_DEVICE_MODIFIER(Name) OMPC_DEVICE_##Name,
#include "clang/Basic/OpenMPKinds.def"
OMPC_DEVICE_unknown,
};
/// OpenMP attributes for 'depend' clause. /// OpenMP attributes for 'depend' clause.
enum OpenMPDependClauseKind { enum OpenMPDependClauseKind {
#define OPENMP_DEPEND_KIND(Name) \ #define OPENMP_DEPEND_KIND(Name) \

View File

@ -3029,11 +3029,13 @@ private:
/// Parses clause with a single expression and an additional argument /// Parses clause with a single expression and an additional argument
/// of a kind \a Kind. /// of a kind \a Kind.
/// ///
/// \param DKind Directive kind.
/// \param Kind Kind of current clause. /// \param Kind Kind of current clause.
/// \param ParseOnly true to skip the clause's semantic actions and return /// \param ParseOnly true to skip the clause's semantic actions and return
/// nullptr. /// nullptr.
/// ///
OMPClause *ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, OMPClause *ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind Kind,
bool ParseOnly); bool ParseOnly);
/// Parses clause without any additional arguments. /// Parses clause without any additional arguments.
/// ///

View File

@ -10576,8 +10576,10 @@ public:
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc); SourceLocation EndLoc);
/// Called on well-formed 'device' clause. /// Called on well-formed 'device' clause.
OMPClause *ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc, OMPClause *ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,
Expr *Device, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation LParenLoc,
SourceLocation ModifierLoc,
SourceLocation EndLoc); SourceLocation EndLoc);
/// Called on well-formed 'map' clause. /// Called on well-formed 'map' clause.
OMPClause * OMPClause *

View File

@ -1433,6 +1433,11 @@ void OMPClausePrinter::VisitOMPSIMDClause(OMPSIMDClause *) { OS << "simd"; }
void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) { void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) {
OS << "device("; OS << "device(";
OpenMPDeviceClauseModifier Modifier = Node->getModifier();
if (Modifier != OMPC_DEVICE_unknown) {
OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Modifier)
<< ": ";
}
Node->getDevice()->printPretty(OS, nullptr, Policy, 0); Node->getDevice()->printPretty(OS, nullptr, Policy, 0);
OS << ")"; OS << ")";
} }

View File

@ -154,6 +154,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
#define OPENMP_DEPEND_KIND(Name) .Case(#Name, OMPC_DEPEND_##Name) #define OPENMP_DEPEND_KIND(Name) .Case(#Name, OMPC_DEPEND_##Name)
#include "clang/Basic/OpenMPKinds.def" #include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_DEPEND_unknown); .Default(OMPC_DEPEND_unknown);
case OMPC_device:
return llvm::StringSwitch<OpenMPDeviceClauseModifier>(Str)
#define OPENMP_DEVICE_MODIFIER(Name) .Case(#Name, OMPC_DEVICE_##Name)
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_DEVICE_unknown);
case OMPC_unknown: case OMPC_unknown:
case OMPC_threadprivate: case OMPC_threadprivate:
case OMPC_if: case OMPC_if:
@ -187,7 +192,6 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_acquire: case OMPC_acquire:
case OMPC_release: case OMPC_release:
case OMPC_relaxed: case OMPC_relaxed:
case OMPC_device:
case OMPC_threads: case OMPC_threads:
case OMPC_simd: case OMPC_simd:
case OMPC_num_teams: case OMPC_num_teams:
@ -380,6 +384,16 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
#include "clang/Basic/OpenMPKinds.def" #include "clang/Basic/OpenMPKinds.def"
} }
llvm_unreachable("Invalid OpenMP 'depend' clause type"); llvm_unreachable("Invalid OpenMP 'depend' clause type");
case OMPC_device:
switch (Type) {
case OMPC_DEVICE_unknown:
return "unknown";
#define OPENMP_DEVICE_MODIFIER(Name) \
case OMPC_DEVICE_##Name: \
return #Name;
#include "clang/Basic/OpenMPKinds.def"
}
llvm_unreachable("Invalid OpenMP 'device' clause modifier");
case OMPC_unknown: case OMPC_unknown:
case OMPC_threadprivate: case OMPC_threadprivate:
case OMPC_if: case OMPC_if:
@ -413,7 +427,6 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_acquire: case OMPC_acquire:
case OMPC_release: case OMPC_release:
case OMPC_relaxed: case OMPC_relaxed:
case OMPC_device:
case OMPC_threads: case OMPC_threads:
case OMPC_simd: case OMPC_simd:
case OMPC_num_teams: case OMPC_num_teams:

View File

@ -4725,8 +4725,11 @@ static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
// Check if we have any device clause associated with the directive. // Check if we have any device clause associated with the directive.
const Expr *Device = nullptr; const Expr *Device = nullptr;
if (auto *C = S.getSingleClause<OMPDeviceClause>()) if (auto *C = S.getSingleClause<OMPDeviceClause>()) {
Device = C->getDevice(); if (C->getModifier() == OMPC_DEVICE_unknown ||
C->getModifier() == OMPC_DEVICE_device_num)
Device = C->getDevice();
}
// Check if we have an if clause whose conditional always evaluates to false // Check if we have an if clause whose conditional always evaluates to false
// or if we do not have any targets specified. If so the target region is not // or if we do not have any targets specified. If so the target region is not

View File

@ -2363,7 +2363,6 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_simdlen: case OMPC_simdlen:
case OMPC_collapse: case OMPC_collapse:
case OMPC_ordered: case OMPC_ordered:
case OMPC_device:
case OMPC_num_teams: case OMPC_num_teams:
case OMPC_thread_limit: case OMPC_thread_limit:
case OMPC_priority: case OMPC_priority:
@ -2379,8 +2378,6 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// Only one safelen clause can appear on a simd directive. // Only one safelen clause can appear on a simd directive.
// Only one simdlen clause can appear on a simd directive. // Only one simdlen clause can appear on a simd directive.
// Only one collapse clause can appear on a simd directive. // Only one collapse clause can appear on a simd directive.
// OpenMP [2.9.1, target data construct, Restrictions]
// At most one device clause can appear on the directive.
// OpenMP [2.11.1, task Construct, Restrictions] // OpenMP [2.11.1, task Construct, Restrictions]
// At most one if clause can appear on the directive. // At most one if clause can appear on the directive.
// At most one final clause can appear on the directive. // At most one final clause can appear on the directive.
@ -2428,6 +2425,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
Clause = ParseOpenMPSimpleClause(CKind, WrongDirective); Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
break; break;
case OMPC_device:
case OMPC_schedule: case OMPC_schedule:
case OMPC_dist_schedule: case OMPC_dist_schedule:
case OMPC_defaultmap: case OMPC_defaultmap:
@ -2435,6 +2433,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// Only one schedule clause can appear on a loop directive. // Only one schedule clause can appear on a loop directive.
// OpenMP 4.5 [2.10.4, Restrictions, p. 106] // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
// At most one defaultmap clause can appear on the directive. // At most one defaultmap clause can appear on the directive.
// OpenMP 5.0 [2.12.5, target construct, Restrictions]
// At most one device clause can appear on the directive.
if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) && if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
!FirstClause) { !FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause) Diag(Tok, diag::err_omp_more_one_clause)
@ -2443,7 +2443,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
} }
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
case OMPC_if: case OMPC_if:
Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective); Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
break; break;
case OMPC_nowait: case OMPC_nowait:
case OMPC_untied: case OMPC_untied:
@ -2677,7 +2677,11 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
/// defaultmap: /// defaultmap:
/// 'defaultmap' '(' modifier ':' kind ')' /// 'defaultmap' '(' modifier ':' kind ')'
/// ///
OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, /// device-clause:
/// 'device' '(' [ device-modifier ':' ] expression ')'
///
OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind Kind,
bool ParseOnly) { bool ParseOnly) {
SourceLocation Loc = ConsumeToken(); SourceLocation Loc = ConsumeToken();
SourceLocation DelimLoc; SourceLocation DelimLoc;
@ -2771,6 +2775,21 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
Tok.isNot(tok::annot_pragma_openmp_end)) Tok.isNot(tok::annot_pragma_openmp_end))
ConsumeAnyToken(); ConsumeAnyToken();
} else if (Kind == OMPC_device) {
// Only target executable directives support extended device construct.
if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
NextToken().is(tok::colon)) {
// Parse optional <device modifier> ':'
Arg.push_back(getOpenMPSimpleClauseType(
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
KLoc.push_back(Tok.getLocation());
ConsumeAnyToken();
// Parse ':'
ConsumeAnyToken();
} else {
Arg.push_back(OMPC_DEVICE_unknown);
KLoc.emplace_back();
}
} else { } else {
assert(Kind == OMPC_if); assert(Kind == OMPC_if);
KLoc.push_back(Tok.getLocation()); KLoc.push_back(Tok.getLocation());
@ -2793,7 +2812,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
(Kind == OMPC_dist_schedule && DelimLoc.isValid()) || (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
Kind == OMPC_if; Kind == OMPC_if || Kind == OMPC_device;
if (NeedAnExpression) { if (NeedAnExpression) {
SourceLocation ELoc = Tok.getLocation(); SourceLocation ELoc = Tok.getLocation();
ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast)); ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));

View File

@ -11043,9 +11043,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_ordered: case OMPC_ordered:
Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr); Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
break; break;
case OMPC_device:
Res = ActOnOpenMPDeviceClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_num_teams: case OMPC_num_teams:
Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc); Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
break; break;
@ -11070,6 +11067,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_detach: case OMPC_detach:
Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc); Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
break; break;
case OMPC_device:
case OMPC_if: case OMPC_if:
case OMPC_default: case OMPC_default:
case OMPC_proc_bind: case OMPC_proc_bind:
@ -12440,6 +12438,12 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind], StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
EndLoc); EndLoc);
break; break;
case OMPC_device:
assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
Res = ActOnOpenMPDeviceClause(
static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
break;
case OMPC_final: case OMPC_final:
case OMPC_num_threads: case OMPC_num_threads:
case OMPC_safelen: case OMPC_safelen:
@ -12477,7 +12481,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_release: case OMPC_release:
case OMPC_relaxed: case OMPC_relaxed:
case OMPC_depend: case OMPC_depend:
case OMPC_device:
case OMPC_threads: case OMPC_threads:
case OMPC_simd: case OMPC_simd:
case OMPC_map: case OMPC_map:
@ -15641,16 +15644,32 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
return C; return C;
} }
OMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc, OMPClause *Sema::ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,
Expr *Device, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation LParenLoc,
SourceLocation ModifierLoc,
SourceLocation EndLoc) { SourceLocation EndLoc) {
assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 50) &&
"Unexpected device modifier in OpenMP < 50.");
bool ErrorFound = false;
if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
std::string Values =
getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
<< Values << getOpenMPClauseName(OMPC_device);
ErrorFound = true;
}
Expr *ValExpr = Device; Expr *ValExpr = Device;
Stmt *HelperValStmt = nullptr; Stmt *HelperValStmt = nullptr;
// OpenMP [2.9.1, Restrictions] // OpenMP [2.9.1, Restrictions]
// The device expression must evaluate to a non-negative integer value. // The device expression must evaluate to a non-negative integer value.
if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_device, ErrorFound = !isNonNegativeIntegerValue(ValExpr, *this, OMPC_device,
/*StrictlyPositive=*/false)) /*StrictlyPositive=*/false) ||
ErrorFound;
if (ErrorFound)
return nullptr; return nullptr;
OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
@ -15663,8 +15682,9 @@ OMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc,
HelperValStmt = buildPreInits(Context, Captures); HelperValStmt = buildPreInits(Context, Captures);
} }
return new (Context) OMPDeviceClause(ValExpr, HelperValStmt, CaptureRegion, return new (Context)
StartLoc, LParenLoc, EndLoc); OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
LParenLoc, ModifierLoc, EndLoc);
} }
static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef,

View File

@ -1847,11 +1847,13 @@ public:
/// ///
/// By default, performs semantic analysis to build the new statement. /// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior. /// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPDeviceClause(Expr *Device, SourceLocation StartLoc, OMPClause *RebuildOMPDeviceClause(OpenMPDeviceClauseModifier Modifier,
Expr *Device, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation LParenLoc,
SourceLocation ModifierLoc,
SourceLocation EndLoc) { SourceLocation EndLoc) {
return getSema().ActOnOpenMPDeviceClause(Device, StartLoc, LParenLoc, return getSema().ActOnOpenMPDeviceClause(Modifier, Device, StartLoc,
EndLoc); LParenLoc, ModifierLoc, EndLoc);
} }
/// Build a new OpenMP 'map' clause. /// Build a new OpenMP 'map' clause.
@ -9256,8 +9258,9 @@ TreeTransform<Derived>::TransformOMPDeviceClause(OMPDeviceClause *C) {
ExprResult E = getDerived().TransformExpr(C->getDevice()); ExprResult E = getDerived().TransformExpr(C->getDevice());
if (E.isInvalid()) if (E.isInvalid())
return nullptr; return nullptr;
return getDerived().RebuildOMPDeviceClause(E.get(), C->getBeginLoc(), return getDerived().RebuildOMPDeviceClause(
C->getLParenLoc(), C->getEndLoc()); C->getModifier(), E.get(), C->getBeginLoc(), C->getLParenLoc(),
C->getModifierLoc(), C->getEndLoc());
} }
template <typename Derived, class T> template <typename Derived, class T>

View File

@ -12294,7 +12294,9 @@ void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) {
void OMPClauseReader::VisitOMPDeviceClause(OMPDeviceClause *C) { void OMPClauseReader::VisitOMPDeviceClause(OMPDeviceClause *C) {
VisitOMPClauseWithPreInit(C); VisitOMPClauseWithPreInit(C);
C->setModifier(Record.readEnum<OpenMPDeviceClauseModifier>());
C->setDevice(Record.readSubExpr()); C->setDevice(Record.readSubExpr());
C->setModifierLoc(Record.readSourceLocation());
C->setLParenLoc(Record.readSourceLocation()); C->setLParenLoc(Record.readSourceLocation());
} }

View File

@ -6376,7 +6376,9 @@ void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) {
void OMPClauseWriter::VisitOMPDeviceClause(OMPDeviceClause *C) { void OMPClauseWriter::VisitOMPDeviceClause(OMPDeviceClause *C) {
VisitOMPClauseWithPreInit(C); VisitOMPClauseWithPreInit(C);
Record.writeEnum(C->getModifier());
Record.AddStmt(C->getDevice()); Record.AddStmt(C->getDevice());
Record.AddSourceLocation(C->getModifierLoc());
Record.AddSourceLocation(C->getLParenLoc()); Record.AddSourceLocation(C->getLParenLoc());
} }

View File

@ -353,11 +353,11 @@ int a;
template <typename T, int C> template <typename T, int C>
T tmain(T argc, T *argv) { T tmain(T argc, T *argv) {
T i, j, a[20], always, close; T i, j, a[20], always, close;
#pragma omp target #pragma omp target device(argc)
foo(); foo();
#pragma omp target if (target:argc > 0) #pragma omp target if (target:argc > 0) device(device_num: C)
foo(); foo();
#pragma omp target if (C) #pragma omp target if (C) device(ancestor: argc)
foo(); foo();
#pragma omp target map(i) #pragma omp target map(i)
foo(); foo();
@ -458,11 +458,11 @@ T tmain(T argc, T *argv) {
// OMP5: template <typename T, int C> T tmain(T argc, T *argv) { // OMP5: template <typename T, int C> T tmain(T argc, T *argv) {
// OMP5-NEXT: T i, j, a[20] // OMP5-NEXT: T i, j, a[20]
// OMP5-NEXT: #pragma omp target{{$}} // OMP5-NEXT: #pragma omp target device(argc){{$}}
// OMP5-NEXT: foo(); // OMP5-NEXT: foo();
// OMP5-NEXT: #pragma omp target if(target: argc > 0) // OMP5-NEXT: #pragma omp target if(target: argc > 0) device(device_num: C)
// OMP5-NEXT: foo() // OMP5-NEXT: foo()
// OMP5-NEXT: #pragma omp target if(C) // OMP5-NEXT: #pragma omp target if(C) device(ancestor: argc)
// OMP5-NEXT: foo() // OMP5-NEXT: foo()
// OMP5-NEXT: #pragma omp target map(tofrom: i) // OMP5-NEXT: #pragma omp target map(tofrom: i)
// OMP5-NEXT: foo() // OMP5-NEXT: foo()
@ -650,11 +650,11 @@ T tmain(T argc, T *argv) {
// OMP5-NEXT: foo() // OMP5-NEXT: foo()
// OMP5: template<> char tmain<char, 1>(char argc, char *argv) { // OMP5: template<> char tmain<char, 1>(char argc, char *argv) {
// OMP5-NEXT: char i, j, a[20] // OMP5-NEXT: char i, j, a[20]
// OMP5-NEXT: #pragma omp target // OMP5-NEXT: #pragma omp target device(argc)
// OMP5-NEXT: foo(); // OMP5-NEXT: foo();
// OMP5-NEXT: #pragma omp target if(target: argc > 0) // OMP5-NEXT: #pragma omp target if(target: argc > 0) device(device_num: 1)
// OMP5-NEXT: foo() // OMP5-NEXT: foo()
// OMP5-NEXT: #pragma omp target if(1) // OMP5-NEXT: #pragma omp target if(1) device(ancestor: argc)
// OMP5-NEXT: foo() // OMP5-NEXT: foo()
// OMP5-NEXT: #pragma omp target map(tofrom: i) // OMP5-NEXT: #pragma omp target map(tofrom: i)
// OMP5-NEXT: foo() // OMP5-NEXT: foo()

View File

@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s -Wuninitialized // RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -fopenmp-version=50 -ferror-limit 100 -o - %s -Wuninitialized
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized // RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 -o - %s -Wuninitialized
void foo() { void foo() {
} }
@ -24,6 +24,7 @@ int main(int argc, char **argv) {
#pragma omp target data map(to: a) device (S1) // expected-error {{'S1' does not refer to a value}} #pragma omp target data map(to: a) device (S1) // expected-error {{'S1' does not refer to a value}}
#pragma omp target data map(to: a) device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}} #pragma omp target data map(to: a) device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}}
#pragma omp target data map(to: a) device (-10u) #pragma omp target data map(to: a) device (-10u)
#pragma omp target data map(to: a) device (ancestor: -10u) // expected-error {{use of undeclared identifier 'ancestor'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target data map(to: a) device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}} #pragma omp target data map(to: a) device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
foo(); foo();

View File

@ -1,6 +1,8 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s -Wuninitialized // RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify=expected,omp45 -fopenmp -fopenmp-version=45 -ferror-limit 100 -o - %s -Wuninitialized
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify=expected,omp50 -fopenmp -fopenmp-version=50 -ferror-limit 100 -o - %s -Wuninitialized
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized // RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify=expected,omp45 -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 -o - %s -Wuninitialized
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 -o - %s -Wuninitialized
void foo() { void foo() {
} }
@ -21,11 +23,13 @@ int main(int argc, char **argv) {
foo(); foo();
#pragma omp target device (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma omp target device (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
foo(); foo();
#pragma omp target device (argc: // expected-error {{expected ')'}} expected-note {{to match this '('}} omp50-error {{expected expression}}
foo();
#pragma omp target device (z-argc)) // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}} #pragma omp target device (z-argc)) // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}}
foo(); foo();
#pragma omp target device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} #pragma omp target device (device_num : argc > 0 ? argv[1] : argv[2]) // omp45-error {{use of undeclared identifier 'device_num'}} omp45-error {{expected ')'}} omp45-note {{to match this '('}} omp50-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
foo(); foo();
#pragma omp target device (argc + argc) #pragma omp target device (argc: argc + argc) // omp45-error {{expected ')'}} omp45-note {{to match this '('}} omp50-error {{expected 'ancestor' or 'device_num' in OpenMP clause 'device'}}
foo(); foo();
#pragma omp target device (argc), device (argc+1) // expected-error {{directive '#pragma omp target' cannot contain more than one 'device' clause}} #pragma omp target device (argc), device (argc+1) // expected-error {{directive '#pragma omp target' cannot contain more than one 'device' clause}}
foo(); foo();
@ -37,6 +41,8 @@ int main(int argc, char **argv) {
foo(); foo();
#pragma omp target device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}} #pragma omp target device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
foo(); foo();
#pragma omp target device (ancestor) // expected-error {{use of undeclared identifier 'ancestor'}}
foo();
return 0; return 0;
} }

View File

@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s -Wuninitialized // RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -fopenmp-version=50 -ferror-limit 100 -o - %s -Wuninitialized
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized // RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 -o - %s -Wuninitialized
void foo() { void foo() {
} }
@ -24,6 +24,7 @@ int main(int argc, char **argv) {
#pragma omp target enter data map(to: i) device (S1) // expected-error {{'S1' does not refer to a value}} #pragma omp target enter data map(to: i) device (S1) // expected-error {{'S1' does not refer to a value}}
#pragma omp target enter data map(to: i) device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}} #pragma omp target enter data map(to: i) device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}}
#pragma omp target enter data map(to: i) device (-10u) #pragma omp target enter data map(to: i) device (-10u)
#pragma omp target enter data map(to: i) device (device_num: -10u) // expected-error {{use of undeclared identifier 'device_num'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target enter data map(to: i) device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}} #pragma omp target enter data map(to: i) device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
foo(); foo();

View File

@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s -Wuninitialized // RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -fopenmp-version=50 -ferror-limit 100 -o - %s -Wuninitialized
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized // RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 -o - %s -Wuninitialized
void foo() { void foo() {
} }
@ -24,6 +24,7 @@ int main(int argc, char **argv) {
#pragma omp target exit data map(from: i) device (S1) // expected-error {{'S1' does not refer to a value}} #pragma omp target exit data map(from: i) device (S1) // expected-error {{'S1' does not refer to a value}}
#pragma omp target exit data map(from: i) device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}} #pragma omp target exit data map(from: i) device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}}
#pragma omp target exit data map(from: i) device (-10u + z) #pragma omp target exit data map(from: i) device (-10u + z)
#pragma omp target exit data map(from: i) device (ancestor: -10u + z) // expected-error {{use of undeclared identifier 'ancestor'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target exit data map(from: i) device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}} #pragma omp target exit data map(from: i) device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
foo(); foo();

View File

@ -1,6 +1,6 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wuninitialized // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ferror-limit 100 %s -Wuninitialized
// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wuninitialized // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 %s -Wuninitialized
void foo() { void foo() {
} }
@ -21,6 +21,7 @@ int tmain(T argc, S **argv) {
#pragma omp target update to(i) device (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} #pragma omp target update to(i) device (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}}
#pragma omp target update from(i) device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} #pragma omp target update from(i) device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
#pragma omp target update from(i) device (argc + z) #pragma omp target update from(i) device (argc + z)
#pragma omp target update from(i) device (device_num: argc + z) // expected-error {{use of undeclared identifier 'device_num'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update from(i) device (argc), device (argc+1) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'device' clause}} #pragma omp target update from(i) device (argc), device (argc+1) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'device' clause}}
#pragma omp target update from(i) device (S1) // expected-error {{'S1' does not refer to a value}} #pragma omp target update from(i) device (S1) // expected-error {{'S1' does not refer to a value}}
#pragma omp target update from(i) device (3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}} #pragma omp target update from(i) device (3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}