summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorDmitry Polukhin <dmitry.polukhin@gmail.com>2016-05-09 14:59:13 +0000
committerDmitry Polukhin <dmitry.polukhin@gmail.com>2016-05-09 14:59:13 +0000
commitd69b505e3c6728013322cd00e3c18d8badacff51 (patch)
tree83ebd3a39bc402044304d291357e08b8e874fd82 /clang/lib
parent98f489ce82f250b31a50b0f1475783642e4ad557 (diff)
downloadbcm5719-llvm-d69b505e3c6728013322cd00e3c18d8badacff51.tar.gz
bcm5719-llvm-d69b505e3c6728013322cd00e3c18d8badacff51.zip
[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
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Frontend/MultiplexConsumer.cpp7
-rw-r--r--clang/lib/Parse/ParseOpenMP.cpp97
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp93
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp6
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp6
5 files changed, 162 insertions, 47 deletions
diff --git a/clang/lib/Frontend/MultiplexConsumer.cpp b/clang/lib/Frontend/MultiplexConsumer.cpp
index 581ed13ce09..17cdaee4be0 100644
--- a/clang/lib/Frontend/MultiplexConsumer.cpp
+++ b/clang/lib/Frontend/MultiplexConsumer.cpp
@@ -125,7 +125,8 @@ public:
void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
void DeclarationMarkedUsed(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 AddedAttributeToRecord(const Attr *Attr,
const RecordDecl *Record) override;
@@ -221,9 +222,9 @@ void MultiplexASTMutationListener::DeclarationMarkedOpenMPThreadPrivate(
Listeners[i]->DeclarationMarkedOpenMPThreadPrivate(D);
}
void MultiplexASTMutationListener::DeclarationMarkedOpenMPDeclareTarget(
- const Decl *D) {
+ const Decl *D, const Attr *Attr) {
for (auto *L : Listeners)
- L->DeclarationMarkedOpenMPDeclareTarget(D);
+ L->DeclarationMarkedOpenMPDeclareTarget(D, Attr);
}
void MultiplexASTMutationListener::RedefinedHiddenDefinition(const NamedDecl *D,
Module *M) {
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index b1538fde257..5a3b4ac825c 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -40,6 +40,21 @@ enum OpenMPDirectiveKindEx {
OMPD_target_enter,
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
// Map token string to extended OMP token kind that are
@@ -525,13 +540,13 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
ParenBraceBracketBalancer BalancerRAIIObj(*this);
SourceLocation Loc = ConsumeToken();
- SmallVector<Expr *, 4> Identifiers;
auto DKind = ParseOpenMPDirectiveKind(*this);
switch (DKind) {
- case OMPD_threadprivate:
+ case OMPD_threadprivate: {
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
// extra tokens.
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
@@ -541,9 +556,11 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
}
// Skip the last annot_pragma_openmp_end.
ConsumeToken();
- return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
+ return Actions.ActOnOpenMPThreadprivateDirective(Loc,
+ Helper.getIdentifiers());
}
break;
+ }
case OMPD_declare_reduction:
ConsumeToken();
if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) {
@@ -599,10 +616,40 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_declare_target: {
SourceLocation DTLoc = ConsumeAnyToken();
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(OMPD_declare_target);
+ // OpenMP 4.5 syntax with list of entities.
+ 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);
+ ConsumeAnyToken();
+ return DeclGroupPtrTy();
}
+
// Skip the last annot_pragma_openmp_end.
ConsumeAnyToken();
@@ -716,7 +763,6 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
AllowedContsructsKind Allowed) {
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
ParenBraceBracketBalancer BalancerRAIIObj(*this);
- SmallVector<Expr *, 5> Identifiers;
SmallVector<OMPClause *, 5> Clauses;
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
FirstClauses(OMPC_unknown + 1);
@@ -732,13 +778,14 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
bool FlushHasClause = false;
switch (DKind) {
- case OMPD_threadprivate:
+ case OMPD_threadprivate: {
if (Allowed != ACK_Any) {
Diag(Tok, diag::err_omp_immediate_directive)
<< getOpenMPDirectiveName(DKind) << 0;
}
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
// extra tokens.
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
@@ -746,12 +793,13 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
<< getOpenMPDirectiveName(OMPD_threadprivate);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}
- DeclGroupPtrTy Res =
- Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
+ DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
+ Loc, Helper.getIdentifiers());
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
}
SkipUntil(tok::annot_pragma_openmp_end);
break;
+ }
case OMPD_declare_reduction:
ConsumeToken();
if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
@@ -913,16 +961,15 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
return Directive;
}
-/// \brief Parses list of simple variables for '#pragma omp threadprivate'
-/// directive.
-///
-/// simple-variable-list:
-/// '(' id-expression {, id-expression} ')'
-///
-bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
- SmallVectorImpl<Expr *> &VarList,
- bool AllowScopeSpecifier) {
- VarList.clear();
+// Parses simple list:
+// simple-variable-list:
+// '(' id-expression {, id-expression} ')'
+//
+bool Parser::ParseOpenMPSimpleVarList(
+ OpenMPDirectiveKind Kind,
+ const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
+ Callback,
+ bool AllowScopeSpecifier) {
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
@@ -959,11 +1006,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
<< tok::identifier
<< SourceRange(PrevTok.getLocation(), PrevTokLocation);
} else {
- DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
- ExprResult Res =
- Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo);
- if (Res.isUsable())
- VarList.push_back(Res.get());
+ Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
}
// Consume ','.
if (Tok.is(tok::comma)) {
@@ -979,7 +1022,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
// Parse ')'.
IsCorrect = !T.consumeClose() && IsCorrect;
- return !IsCorrect && VarList.empty();
+ return !IsCorrect;
}
/// \brief Parsing of OpenMP clauses.
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index cbcf70b41fc..ea26f6a4f16 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -1101,6 +1101,23 @@ public:
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
ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
@@ -10752,6 +10769,52 @@ void Sema::ActOnFinishOpenMPDeclareTargetDirective() {
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,
Sema &SemaRef, Decl *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
// anything.
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())
- ML->DeclarationMarkedOpenMPDeclareTarget(D);
+ ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
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
// to do anything else.
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())
- ML->DeclarationMarkedOpenMPDeclareTarget(D);
+ ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
return;
}
}
@@ -10810,9 +10877,11 @@ static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
SemaRef.Diag(SL, diag::note_used_here) << SR;
}
// 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())
- ML->DeclarationMarkedOpenMPDeclareTarget(D);
+ ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
}
}
@@ -10846,9 +10915,11 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D) {
!checkValueDeclInTarget(SL, SR, *this, DSAStack, VD)) {
// Mark decl as declared target to prevent further diagnostic.
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())
- ML->DeclarationMarkedOpenMPDeclareTarget(VD);
+ ML->DeclarationMarkedOpenMPDeclareTarget(VD, A);
}
return;
}
@@ -10857,9 +10928,11 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D) {
// Checking declaration inside declare target region.
if (!D->hasAttr<OMPDeclareTargetDeclAttr>() &&
(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())
- ML->DeclarationMarkedOpenMPDeclareTarget(D);
+ ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
}
return;
}
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 1a013cee219..6b933f2bba1 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -3890,11 +3890,6 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
Reader.Context, ReadSourceRange(Record, Idx)));
break;
- case UPD_DECL_MARKED_OPENMP_DECLARETARGET:
- D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(
- Reader.Context, ReadSourceRange(Record, Idx)));
- break;
-
case UPD_DECL_EXPORTED: {
unsigned SubmoduleID = readSubmoduleID(Record, Idx);
auto *Exported = cast<NamedDecl>(D);
@@ -3920,6 +3915,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
break;
}
+ case UPD_DECL_MARKED_OPENMP_DECLARETARGET:
case UPD_ADDED_ATTR_TO_RECORD:
AttrVec Attrs;
Reader.ReadAttributes(F, Attrs, Record, Idx);
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 606228af753..29a20b2e45e 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -5816,12 +5816,14 @@ void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {
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!");
if (!D->isFromASTFile())
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) {
OpenPOWER on IntegriCloud