forked from OSchip/llvm-project
[OpenMP] Parse+Sema for '#pragma omp declare target' syntax version 4.5
Support OpenMP version 4.5 syntax for #pragma omp declare target. Syntax: #pragma omp declare target (extended-list) new-line or #pragma omp declare target clause[ [,] clause ... ] new-line Where clause is one of the following: to(extended-list) link(list) Differential Revision: http://reviews.llvm.org/D20011 llvm-svn: 268925
This commit is contained in:
parent
98f489ce82
commit
d69b505e3c
|
@ -111,7 +111,9 @@ public:
|
||||||
/// previously marked as declaretarget.
|
/// previously marked as declaretarget.
|
||||||
///
|
///
|
||||||
/// \param D the declaration marked OpenMP declaretarget.
|
/// \param D the declaration marked OpenMP declaretarget.
|
||||||
virtual void DeclarationMarkedOpenMPDeclareTarget(const Decl *D) {}
|
/// \param Attr the added attribute.
|
||||||
|
virtual void DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
|
||||||
|
const Attr *Attr) {}
|
||||||
|
|
||||||
/// \brief A definition has been made visible by being redefined locally.
|
/// \brief A definition has been made visible by being redefined locally.
|
||||||
///
|
///
|
||||||
|
|
|
@ -2345,8 +2345,17 @@ def OMPDeclareTargetDecl : Attr {
|
||||||
let Spellings = [Pragma<"omp", "declare target">];
|
let Spellings = [Pragma<"omp", "declare target">];
|
||||||
let SemaHandler = 0;
|
let SemaHandler = 0;
|
||||||
let Documentation = [OMPDeclareTargetDocs];
|
let Documentation = [OMPDeclareTargetDocs];
|
||||||
|
let Args = [
|
||||||
|
EnumArgument<"MapType", "MapTypeTy",
|
||||||
|
[ "to", "link" ],
|
||||||
|
[ "MT_To", "MT_Link" ]>
|
||||||
|
];
|
||||||
let AdditionalMembers = [{
|
let AdditionalMembers = [{
|
||||||
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {}
|
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
|
||||||
|
// Use fake syntax because it is for testing and debugging purpose only.
|
||||||
|
if (getMapType() != MT_To)
|
||||||
|
OS << ConvertMapTypeTyToStr(getMapType()) << " ";
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -967,6 +967,8 @@ def err_omp_declare_simd_inbranch_notinbranch : Error<
|
||||||
"unexpected '%0' clause, '%1' is specified already">;
|
"unexpected '%0' clause, '%1' is specified already">;
|
||||||
def err_expected_end_declare_target : Error<
|
def err_expected_end_declare_target : Error<
|
||||||
"expected '#pragma omp end declare target'">;
|
"expected '#pragma omp end declare target'">;
|
||||||
|
def err_omp_declare_target_unexpected_clause: Error<
|
||||||
|
"unexpected '%0' clause, only 'to' or 'link' clauses expected">;
|
||||||
|
|
||||||
// Pragma loop support.
|
// Pragma loop support.
|
||||||
def err_pragma_loop_missing_argument : Error<
|
def err_pragma_loop_missing_argument : Error<
|
||||||
|
|
|
@ -7984,6 +7984,12 @@ def warn_omp_alignment_not_power_of_two : Warning<
|
||||||
InGroup<OpenMPClauses>;
|
InGroup<OpenMPClauses>;
|
||||||
def err_omp_enclosed_declare_target : Error<
|
def err_omp_enclosed_declare_target : Error<
|
||||||
"declare target region may not be enclosed within another declare target region">;
|
"declare target region may not be enclosed within another declare target region">;
|
||||||
|
def err_omp_invalid_target_decl : Error<
|
||||||
|
"%0 used in declare target directive is not a variable or a function name">;
|
||||||
|
def err_omp_declare_target_multiple : Error<
|
||||||
|
"%0 appears multiple times in clauses on the same declare target directive">;
|
||||||
|
def err_omp_declare_target_to_and_link : Error<
|
||||||
|
"%0 must not appear in both clauses 'to' and 'link'">;
|
||||||
def warn_omp_not_in_target_context : Warning<
|
def warn_omp_not_in_target_context : Warning<
|
||||||
"declaration is not declared in any declare target region">,
|
"declaration is not declared in any declare target region">,
|
||||||
InGroup<OpenMPTarget>;
|
InGroup<OpenMPTarget>;
|
||||||
|
|
|
@ -2466,16 +2466,19 @@ private:
|
||||||
Decl *TagDecl = nullptr);
|
Decl *TagDecl = nullptr);
|
||||||
/// \brief Parse 'omp declare reduction' construct.
|
/// \brief Parse 'omp declare reduction' construct.
|
||||||
DeclGroupPtrTy ParseOpenMPDeclareReductionDirective(AccessSpecifier AS);
|
DeclGroupPtrTy ParseOpenMPDeclareReductionDirective(AccessSpecifier AS);
|
||||||
|
|
||||||
/// \brief Parses simple list of variables.
|
/// \brief Parses simple list of variables.
|
||||||
///
|
///
|
||||||
/// \param Kind Kind of the directive.
|
/// \param Kind Kind of the directive.
|
||||||
/// \param [out] VarList List of referenced variables.
|
/// \param Callback Callback function to be called for the list elements.
|
||||||
/// \param AllowScopeSpecifier true, if the variables can have fully
|
/// \param AllowScopeSpecifier true, if the variables can have fully
|
||||||
/// qualified names.
|
/// qualified names.
|
||||||
///
|
///
|
||||||
bool ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
|
bool ParseOpenMPSimpleVarList(
|
||||||
SmallVectorImpl<Expr *> &VarList,
|
OpenMPDirectiveKind Kind,
|
||||||
bool AllowScopeSpecifier);
|
const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
|
||||||
|
Callback,
|
||||||
|
bool AllowScopeSpecifier);
|
||||||
/// \brief Parses declarative or executable directive.
|
/// \brief Parses declarative or executable directive.
|
||||||
///
|
///
|
||||||
/// \param Allowed ACK_Any, if any directives are allowed,
|
/// \param Allowed ACK_Any, if any directives are allowed,
|
||||||
|
|
|
@ -7977,6 +7977,11 @@ public:
|
||||||
bool ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc);
|
bool ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc);
|
||||||
/// Called at the end of target region i.e. '#pragme omp end declare target'.
|
/// Called at the end of target region i.e. '#pragme omp end declare target'.
|
||||||
void ActOnFinishOpenMPDeclareTargetDirective();
|
void ActOnFinishOpenMPDeclareTargetDirective();
|
||||||
|
/// Called on correct id-expression from the '#pragma omp declare target'.
|
||||||
|
void ActOnOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec,
|
||||||
|
const DeclarationNameInfo &Id,
|
||||||
|
OMPDeclareTargetDeclAttr::MapTypeTy MT,
|
||||||
|
NamedDeclSetType &SameDirectiveDecls);
|
||||||
/// Check declaration inside target region.
|
/// Check declaration inside target region.
|
||||||
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D);
|
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D);
|
||||||
/// Return true inside OpenMP target region.
|
/// Return true inside OpenMP target region.
|
||||||
|
|
|
@ -682,7 +682,8 @@ private:
|
||||||
const ObjCInterfaceDecl *IFD) override;
|
const ObjCInterfaceDecl *IFD) override;
|
||||||
void DeclarationMarkedUsed(const Decl *D) override;
|
void DeclarationMarkedUsed(const Decl *D) override;
|
||||||
void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
|
void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
|
||||||
void DeclarationMarkedOpenMPDeclareTarget(const Decl *D) override;
|
void DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
|
||||||
|
const Attr *Attr) override;
|
||||||
void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;
|
void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;
|
||||||
void AddedAttributeToRecord(const Attr *Attr,
|
void AddedAttributeToRecord(const Attr *Attr,
|
||||||
const RecordDecl *Record) override;
|
const RecordDecl *Record) override;
|
||||||
|
|
|
@ -125,7 +125,8 @@ public:
|
||||||
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
|
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
|
||||||
void DeclarationMarkedUsed(const Decl *D) override;
|
void DeclarationMarkedUsed(const Decl *D) override;
|
||||||
void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
|
void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
|
||||||
void DeclarationMarkedOpenMPDeclareTarget(const Decl *D) override;
|
void DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
|
||||||
|
const Attr *Attr) override;
|
||||||
void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;
|
void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;
|
||||||
void AddedAttributeToRecord(const Attr *Attr,
|
void AddedAttributeToRecord(const Attr *Attr,
|
||||||
const RecordDecl *Record) override;
|
const RecordDecl *Record) override;
|
||||||
|
@ -221,9 +222,9 @@ void MultiplexASTMutationListener::DeclarationMarkedOpenMPThreadPrivate(
|
||||||
Listeners[i]->DeclarationMarkedOpenMPThreadPrivate(D);
|
Listeners[i]->DeclarationMarkedOpenMPThreadPrivate(D);
|
||||||
}
|
}
|
||||||
void MultiplexASTMutationListener::DeclarationMarkedOpenMPDeclareTarget(
|
void MultiplexASTMutationListener::DeclarationMarkedOpenMPDeclareTarget(
|
||||||
const Decl *D) {
|
const Decl *D, const Attr *Attr) {
|
||||||
for (auto *L : Listeners)
|
for (auto *L : Listeners)
|
||||||
L->DeclarationMarkedOpenMPDeclareTarget(D);
|
L->DeclarationMarkedOpenMPDeclareTarget(D, Attr);
|
||||||
}
|
}
|
||||||
void MultiplexASTMutationListener::RedefinedHiddenDefinition(const NamedDecl *D,
|
void MultiplexASTMutationListener::RedefinedHiddenDefinition(const NamedDecl *D,
|
||||||
Module *M) {
|
Module *M) {
|
||||||
|
|
|
@ -40,6 +40,21 @@ enum OpenMPDirectiveKindEx {
|
||||||
OMPD_target_enter,
|
OMPD_target_enter,
|
||||||
OMPD_target_exit
|
OMPD_target_exit
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ThreadprivateListParserHelper final {
|
||||||
|
SmallVector<Expr *, 4> Identifiers;
|
||||||
|
Parser *P;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ThreadprivateListParserHelper(Parser *P) : P(P) {}
|
||||||
|
void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
|
||||||
|
ExprResult Res =
|
||||||
|
P->getActions().ActOnOpenMPIdExpression(P->getCurScope(), SS, NameInfo);
|
||||||
|
if (Res.isUsable())
|
||||||
|
Identifiers.push_back(Res.get());
|
||||||
|
}
|
||||||
|
llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
|
||||||
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// Map token string to extended OMP token kind that are
|
// Map token string to extended OMP token kind that are
|
||||||
|
@ -525,13 +540,13 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
|
||||||
ParenBraceBracketBalancer BalancerRAIIObj(*this);
|
ParenBraceBracketBalancer BalancerRAIIObj(*this);
|
||||||
|
|
||||||
SourceLocation Loc = ConsumeToken();
|
SourceLocation Loc = ConsumeToken();
|
||||||
SmallVector<Expr *, 4> Identifiers;
|
|
||||||
auto DKind = ParseOpenMPDirectiveKind(*this);
|
auto DKind = ParseOpenMPDirectiveKind(*this);
|
||||||
|
|
||||||
switch (DKind) {
|
switch (DKind) {
|
||||||
case OMPD_threadprivate:
|
case OMPD_threadprivate: {
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
|
ThreadprivateListParserHelper Helper(this);
|
||||||
|
if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) {
|
||||||
// The last seen token is annot_pragma_openmp_end - need to check for
|
// The last seen token is annot_pragma_openmp_end - need to check for
|
||||||
// extra tokens.
|
// extra tokens.
|
||||||
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
||||||
|
@ -541,9 +556,11 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
|
||||||
}
|
}
|
||||||
// Skip the last annot_pragma_openmp_end.
|
// Skip the last annot_pragma_openmp_end.
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
|
return Actions.ActOnOpenMPThreadprivateDirective(Loc,
|
||||||
|
Helper.getIdentifiers());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case OMPD_declare_reduction:
|
case OMPD_declare_reduction:
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) {
|
if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) {
|
||||||
|
@ -599,10 +616,40 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
|
||||||
case OMPD_declare_target: {
|
case OMPD_declare_target: {
|
||||||
SourceLocation DTLoc = ConsumeAnyToken();
|
SourceLocation DTLoc = ConsumeAnyToken();
|
||||||
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
||||||
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
|
// OpenMP 4.5 syntax with list of entities.
|
||||||
<< getOpenMPDirectiveName(OMPD_declare_target);
|
llvm::SmallSetVector<const NamedDecl*, 16> SameDirectiveDecls;
|
||||||
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
||||||
|
OMPDeclareTargetDeclAttr::MapTypeTy MT =
|
||||||
|
OMPDeclareTargetDeclAttr::MT_To;
|
||||||
|
if (Tok.is(tok::identifier)) {
|
||||||
|
IdentifierInfo *II = Tok.getIdentifierInfo();
|
||||||
|
StringRef ClauseName = II->getName();
|
||||||
|
// Parse 'to|link' clauses.
|
||||||
|
if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName,
|
||||||
|
MT)) {
|
||||||
|
Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
|
||||||
|
<< ClauseName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ConsumeToken();
|
||||||
|
}
|
||||||
|
auto Callback = [this, MT, &SameDirectiveDecls](
|
||||||
|
CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
|
||||||
|
Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
|
||||||
|
SameDirectiveDecls);
|
||||||
|
};
|
||||||
|
if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, true))
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Consume optional ','.
|
||||||
|
if (Tok.is(tok::comma))
|
||||||
|
ConsumeToken();
|
||||||
|
}
|
||||||
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
||||||
|
ConsumeAnyToken();
|
||||||
|
return DeclGroupPtrTy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip the last annot_pragma_openmp_end.
|
// Skip the last annot_pragma_openmp_end.
|
||||||
ConsumeAnyToken();
|
ConsumeAnyToken();
|
||||||
|
|
||||||
|
@ -716,7 +763,6 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
|
||||||
AllowedContsructsKind Allowed) {
|
AllowedContsructsKind Allowed) {
|
||||||
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
|
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
|
||||||
ParenBraceBracketBalancer BalancerRAIIObj(*this);
|
ParenBraceBracketBalancer BalancerRAIIObj(*this);
|
||||||
SmallVector<Expr *, 5> Identifiers;
|
|
||||||
SmallVector<OMPClause *, 5> Clauses;
|
SmallVector<OMPClause *, 5> Clauses;
|
||||||
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
|
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
|
||||||
FirstClauses(OMPC_unknown + 1);
|
FirstClauses(OMPC_unknown + 1);
|
||||||
|
@ -732,13 +778,14 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
|
||||||
bool FlushHasClause = false;
|
bool FlushHasClause = false;
|
||||||
|
|
||||||
switch (DKind) {
|
switch (DKind) {
|
||||||
case OMPD_threadprivate:
|
case OMPD_threadprivate: {
|
||||||
if (Allowed != ACK_Any) {
|
if (Allowed != ACK_Any) {
|
||||||
Diag(Tok, diag::err_omp_immediate_directive)
|
Diag(Tok, diag::err_omp_immediate_directive)
|
||||||
<< getOpenMPDirectiveName(DKind) << 0;
|
<< getOpenMPDirectiveName(DKind) << 0;
|
||||||
}
|
}
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
|
ThreadprivateListParserHelper Helper(this);
|
||||||
|
if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) {
|
||||||
// The last seen token is annot_pragma_openmp_end - need to check for
|
// The last seen token is annot_pragma_openmp_end - need to check for
|
||||||
// extra tokens.
|
// extra tokens.
|
||||||
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
||||||
|
@ -746,12 +793,13 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
|
||||||
<< getOpenMPDirectiveName(OMPD_threadprivate);
|
<< getOpenMPDirectiveName(OMPD_threadprivate);
|
||||||
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
||||||
}
|
}
|
||||||
DeclGroupPtrTy Res =
|
DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
|
||||||
Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
|
Loc, Helper.getIdentifiers());
|
||||||
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
|
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
|
||||||
}
|
}
|
||||||
SkipUntil(tok::annot_pragma_openmp_end);
|
SkipUntil(tok::annot_pragma_openmp_end);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case OMPD_declare_reduction:
|
case OMPD_declare_reduction:
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
|
if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
|
||||||
|
@ -913,16 +961,15 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
|
||||||
return Directive;
|
return Directive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Parses list of simple variables for '#pragma omp threadprivate'
|
// Parses simple list:
|
||||||
/// directive.
|
// simple-variable-list:
|
||||||
///
|
// '(' id-expression {, id-expression} ')'
|
||||||
/// simple-variable-list:
|
//
|
||||||
/// '(' id-expression {, id-expression} ')'
|
bool Parser::ParseOpenMPSimpleVarList(
|
||||||
///
|
OpenMPDirectiveKind Kind,
|
||||||
bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
|
const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
|
||||||
SmallVectorImpl<Expr *> &VarList,
|
Callback,
|
||||||
bool AllowScopeSpecifier) {
|
bool AllowScopeSpecifier) {
|
||||||
VarList.clear();
|
|
||||||
// Parse '('.
|
// Parse '('.
|
||||||
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
||||||
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
||||||
|
@ -959,11 +1006,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
|
||||||
<< tok::identifier
|
<< tok::identifier
|
||||||
<< SourceRange(PrevTok.getLocation(), PrevTokLocation);
|
<< SourceRange(PrevTok.getLocation(), PrevTokLocation);
|
||||||
} else {
|
} else {
|
||||||
DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
|
Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
|
||||||
ExprResult Res =
|
|
||||||
Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo);
|
|
||||||
if (Res.isUsable())
|
|
||||||
VarList.push_back(Res.get());
|
|
||||||
}
|
}
|
||||||
// Consume ','.
|
// Consume ','.
|
||||||
if (Tok.is(tok::comma)) {
|
if (Tok.is(tok::comma)) {
|
||||||
|
@ -979,7 +1022,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
|
||||||
// Parse ')'.
|
// Parse ')'.
|
||||||
IsCorrect = !T.consumeClose() && IsCorrect;
|
IsCorrect = !T.consumeClose() && IsCorrect;
|
||||||
|
|
||||||
return !IsCorrect && VarList.empty();
|
return !IsCorrect;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Parsing of OpenMP clauses.
|
/// \brief Parsing of OpenMP clauses.
|
||||||
|
|
|
@ -1101,6 +1101,23 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class VarOrFuncDeclFilterCCC : public CorrectionCandidateCallback {
|
||||||
|
private:
|
||||||
|
Sema &SemaRef;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
|
||||||
|
bool ValidateCandidate(const TypoCorrection &Candidate) override {
|
||||||
|
NamedDecl *ND = Candidate.getCorrectionDecl();
|
||||||
|
if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) {
|
||||||
|
return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
|
||||||
|
SemaRef.getCurScope());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
|
ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
|
||||||
|
@ -10752,6 +10769,52 @@ void Sema::ActOnFinishOpenMPDeclareTargetDirective() {
|
||||||
IsInOpenMPDeclareTargetContext = false;
|
IsInOpenMPDeclareTargetContext = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec,
|
||||||
|
const DeclarationNameInfo &Id,
|
||||||
|
OMPDeclareTargetDeclAttr::MapTypeTy MT,
|
||||||
|
NamedDeclSetType &SameDirectiveDecls) {
|
||||||
|
LookupResult Lookup(*this, Id, LookupOrdinaryName);
|
||||||
|
LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
|
||||||
|
|
||||||
|
if (Lookup.isAmbiguous())
|
||||||
|
return;
|
||||||
|
Lookup.suppressDiagnostics();
|
||||||
|
|
||||||
|
if (!Lookup.isSingleResult()) {
|
||||||
|
if (TypoCorrection Corrected =
|
||||||
|
CorrectTypo(Id, LookupOrdinaryName, CurScope, nullptr,
|
||||||
|
llvm::make_unique<VarOrFuncDeclFilterCCC>(*this),
|
||||||
|
CTK_ErrorRecovery)) {
|
||||||
|
diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
|
||||||
|
<< Id.getName());
|
||||||
|
checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
|
||||||
|
if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) {
|
||||||
|
if (!SameDirectiveDecls.insert(cast<NamedDecl>(ND->getCanonicalDecl())))
|
||||||
|
Diag(Id.getLoc(), diag::err_omp_declare_target_multiple) << Id.getName();
|
||||||
|
|
||||||
|
if (!ND->hasAttr<OMPDeclareTargetDeclAttr>()) {
|
||||||
|
Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT);
|
||||||
|
ND->addAttr(A);
|
||||||
|
if (ASTMutationListener *ML = Context.getASTMutationListener())
|
||||||
|
ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
|
||||||
|
checkDeclIsAllowedInOpenMPTarget(nullptr, ND);
|
||||||
|
} else if (ND->getAttr<OMPDeclareTargetDeclAttr>()->getMapType() != MT) {
|
||||||
|
Diag(Id.getLoc(), diag::err_omp_declare_target_to_and_link)
|
||||||
|
<< Id.getName();
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
|
||||||
|
}
|
||||||
|
|
||||||
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
|
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
|
||||||
Sema &SemaRef, Decl *D) {
|
Sema &SemaRef, Decl *D) {
|
||||||
if (!D)
|
if (!D)
|
||||||
|
@ -10765,9 +10828,11 @@ static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
|
||||||
// If this is an implicit variable that is legal and we do not need to do
|
// If this is an implicit variable that is legal and we do not need to do
|
||||||
// anything.
|
// anything.
|
||||||
if (cast<VarDecl>(D)->isImplicit()) {
|
if (cast<VarDecl>(D)->isImplicit()) {
|
||||||
D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(SemaRef.Context));
|
Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
|
||||||
|
SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
|
||||||
|
D->addAttr(A);
|
||||||
if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
|
if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
|
||||||
ML->DeclarationMarkedOpenMPDeclareTarget(D);
|
ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10780,9 +10845,11 @@ static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
|
||||||
// target region (it can be e.g. a lambda) that is legal and we do not need
|
// target region (it can be e.g. a lambda) that is legal and we do not need
|
||||||
// to do anything else.
|
// to do anything else.
|
||||||
if (LD == D) {
|
if (LD == D) {
|
||||||
D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(SemaRef.Context));
|
Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
|
||||||
|
SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
|
||||||
|
D->addAttr(A);
|
||||||
if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
|
if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
|
||||||
ML->DeclarationMarkedOpenMPDeclareTarget(D);
|
ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10810,9 +10877,11 @@ static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
|
||||||
SemaRef.Diag(SL, diag::note_used_here) << SR;
|
SemaRef.Diag(SL, diag::note_used_here) << SR;
|
||||||
}
|
}
|
||||||
// Mark decl as declared target to prevent further diagnostic.
|
// Mark decl as declared target to prevent further diagnostic.
|
||||||
D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(SemaRef.Context));
|
Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
|
||||||
|
SemaRef.Context, OMPDeclareTargetDeclAttr::MT_To);
|
||||||
|
D->addAttr(A);
|
||||||
if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
|
if (ASTMutationListener *ML = SemaRef.Context.getASTMutationListener())
|
||||||
ML->DeclarationMarkedOpenMPDeclareTarget(D);
|
ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10846,9 +10915,11 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D) {
|
||||||
!checkValueDeclInTarget(SL, SR, *this, DSAStack, VD)) {
|
!checkValueDeclInTarget(SL, SR, *this, DSAStack, VD)) {
|
||||||
// Mark decl as declared target to prevent further diagnostic.
|
// Mark decl as declared target to prevent further diagnostic.
|
||||||
if (isa<VarDecl>(VD) || isa<FunctionDecl>(VD)) {
|
if (isa<VarDecl>(VD) || isa<FunctionDecl>(VD)) {
|
||||||
VD->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(Context));
|
Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
|
||||||
|
Context, OMPDeclareTargetDeclAttr::MT_To);
|
||||||
|
VD->addAttr(A);
|
||||||
if (ASTMutationListener *ML = Context.getASTMutationListener())
|
if (ASTMutationListener *ML = Context.getASTMutationListener())
|
||||||
ML->DeclarationMarkedOpenMPDeclareTarget(VD);
|
ML->DeclarationMarkedOpenMPDeclareTarget(VD, A);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -10857,9 +10928,11 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D) {
|
||||||
// Checking declaration inside declare target region.
|
// Checking declaration inside declare target region.
|
||||||
if (!D->hasAttr<OMPDeclareTargetDeclAttr>() &&
|
if (!D->hasAttr<OMPDeclareTargetDeclAttr>() &&
|
||||||
(isa<VarDecl>(D) || isa<FunctionDecl>(D))) {
|
(isa<VarDecl>(D) || isa<FunctionDecl>(D))) {
|
||||||
D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(Context));
|
Attr *A = OMPDeclareTargetDeclAttr::CreateImplicit(
|
||||||
|
Context, OMPDeclareTargetDeclAttr::MT_To);
|
||||||
|
D->addAttr(A);
|
||||||
if (ASTMutationListener *ML = Context.getASTMutationListener())
|
if (ASTMutationListener *ML = Context.getASTMutationListener())
|
||||||
ML->DeclarationMarkedOpenMPDeclareTarget(D);
|
ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3890,11 +3890,6 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
|
||||||
Reader.Context, ReadSourceRange(Record, Idx)));
|
Reader.Context, ReadSourceRange(Record, Idx)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UPD_DECL_MARKED_OPENMP_DECLARETARGET:
|
|
||||||
D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(
|
|
||||||
Reader.Context, ReadSourceRange(Record, Idx)));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UPD_DECL_EXPORTED: {
|
case UPD_DECL_EXPORTED: {
|
||||||
unsigned SubmoduleID = readSubmoduleID(Record, Idx);
|
unsigned SubmoduleID = readSubmoduleID(Record, Idx);
|
||||||
auto *Exported = cast<NamedDecl>(D);
|
auto *Exported = cast<NamedDecl>(D);
|
||||||
|
@ -3920,6 +3915,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case UPD_DECL_MARKED_OPENMP_DECLARETARGET:
|
||||||
case UPD_ADDED_ATTR_TO_RECORD:
|
case UPD_ADDED_ATTR_TO_RECORD:
|
||||||
AttrVec Attrs;
|
AttrVec Attrs;
|
||||||
Reader.ReadAttributes(F, Attrs, Record, Idx);
|
Reader.ReadAttributes(F, Attrs, Record, Idx);
|
||||||
|
|
|
@ -5816,12 +5816,14 @@ void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {
|
||||||
DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_THREADPRIVATE));
|
DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_THREADPRIVATE));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D) {
|
void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
|
||||||
|
const Attr *Attr) {
|
||||||
assert(!WritingAST && "Already writing the AST!");
|
assert(!WritingAST && "Already writing the AST!");
|
||||||
if (!D->isFromASTFile())
|
if (!D->isFromASTFile())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_DECLARETARGET));
|
DeclUpdates[D].push_back(
|
||||||
|
DeclUpdate(UPD_DECL_MARKED_OPENMP_DECLARETARGET, Attr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {
|
void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {
|
||||||
|
|
|
@ -79,6 +79,51 @@ int test1() {
|
||||||
#pragma omp end declare target
|
#pragma omp end declare target
|
||||||
// CHECK: #pragma omp end declare target
|
// CHECK: #pragma omp end declare target
|
||||||
|
|
||||||
|
int a1;
|
||||||
|
void f1() {
|
||||||
|
}
|
||||||
|
#pragma omp declare target (a1, f1)
|
||||||
|
// CHECK: #pragma omp declare target
|
||||||
|
// CHECK: int a1;
|
||||||
|
// CHECK: #pragma omp end declare target
|
||||||
|
// CHECK: #pragma omp declare target
|
||||||
|
// CHECK: void f1()
|
||||||
|
// CHECK: #pragma omp end declare target
|
||||||
|
|
||||||
|
int b1, b2, b3;
|
||||||
|
void f2() {
|
||||||
|
}
|
||||||
|
#pragma omp declare target to(b1) to(b2), to(b3, f2)
|
||||||
|
// CHECK: #pragma omp declare target
|
||||||
|
// CHECK: int b1;
|
||||||
|
// CHECK: #pragma omp end declare target
|
||||||
|
// CHECK: #pragma omp declare target
|
||||||
|
// CHECK: int b2;
|
||||||
|
// CHECK: #pragma omp end declare target
|
||||||
|
// CHECK: #pragma omp declare target
|
||||||
|
// CHECK: int b3;
|
||||||
|
// CHECK: #pragma omp end declare target
|
||||||
|
// CHECK: #pragma omp declare target
|
||||||
|
// CHECK: void f2()
|
||||||
|
// CHECK: #pragma omp end declare target
|
||||||
|
|
||||||
|
int c1, c2, c3;
|
||||||
|
void f3() {
|
||||||
|
}
|
||||||
|
#pragma omp declare target link(c1) link(c2), link(c3, f3)
|
||||||
|
// CHECK: #pragma omp declare target link
|
||||||
|
// CHECK: int c1;
|
||||||
|
// CHECK: #pragma omp end declare target
|
||||||
|
// CHECK: #pragma omp declare target link
|
||||||
|
// CHECK: int c2;
|
||||||
|
// CHECK: #pragma omp end declare target
|
||||||
|
// CHECK: #pragma omp declare target link
|
||||||
|
// CHECK: int c3;
|
||||||
|
// CHECK: #pragma omp end declare target
|
||||||
|
// CHECK: #pragma omp declare target link
|
||||||
|
// CHECK: void f3()
|
||||||
|
// CHECK: #pragma omp end declare target
|
||||||
|
|
||||||
int main (int argc, char **argv) {
|
int main (int argc, char **argv) {
|
||||||
foo();
|
foo();
|
||||||
foo_c();
|
foo_c();
|
||||||
|
|
|
@ -4,9 +4,15 @@
|
||||||
|
|
||||||
int a, b; // expected-warning {{declaration is not declared in any declare target region}}
|
int a, b; // expected-warning {{declaration is not declared in any declare target region}}
|
||||||
__thread int t; // expected-note {{defined as threadprivate or thread local}}
|
__thread int t; // expected-note {{defined as threadprivate or thread local}}
|
||||||
#pragma omp declare target private(a) // expected-warning {{extra tokens at the end of '#pragma omp declare target' are ignored}}
|
|
||||||
|
#pragma omp declare target . // expected-error {{expected '(' after 'declare target'}}
|
||||||
|
|
||||||
|
#pragma omp declare target
|
||||||
void f();
|
void f();
|
||||||
#pragma omp end declare target shared(a) // expected-warning {{extra tokens at the end of '#pragma omp end declare target' are ignored}}
|
#pragma omp end declare target shared(a) // expected-warning {{extra tokens at the end of '#pragma omp end declare target' are ignored}}
|
||||||
|
|
||||||
|
#pragma omp declare target map(a) // expected-error {{unexpected 'map' clause, only 'to' or 'link' clauses expected}}
|
||||||
|
|
||||||
void c(); // expected-warning {{declaration is not declared in any declare target region}}
|
void c(); // expected-warning {{declaration is not declared in any declare target region}}
|
||||||
|
|
||||||
extern int b;
|
extern int b;
|
||||||
|
@ -86,4 +92,10 @@ namespace {
|
||||||
} // expected-error {{expected '#pragma omp end declare target'}}
|
} // expected-error {{expected '#pragma omp end declare target'}}
|
||||||
#pragma omp end declare target // expected-error {{unexpected OpenMP directive '#pragma omp end declare target'}}
|
#pragma omp end declare target // expected-error {{unexpected OpenMP directive '#pragma omp end declare target'}}
|
||||||
|
|
||||||
|
#pragma omp declare target link(S) // expected-error {{'S' used in declare target directive is not a variable or a function name}}
|
||||||
|
|
||||||
|
#pragma omp declare target (x, x) // expected-error {{'x' appears multiple times in clauses on the same declare target directive}}
|
||||||
|
#pragma omp declare target to(x) to(x) // expected-error {{'x' appears multiple times in clauses on the same declare target directive}}
|
||||||
|
#pragma omp declare target link(x) // expected-error {{'x' must not appear in both clauses 'to' and 'link'}}
|
||||||
|
|
||||||
#pragma omp declare target // expected-error {{expected '#pragma omp end declare target'}} expected-note {{to match this '#pragma omp declare target'}}
|
#pragma omp declare target // expected-error {{expected '#pragma omp end declare target'}} expected-note {{to match this '#pragma omp declare target'}}
|
||||||
|
|
Loading…
Reference in New Issue