summaryrefslogtreecommitdiff
path: root/lib/Parse/ParseOpenMP.cpp
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2019-10-08 17:47:52 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2019-10-08 17:47:52 +0000
commitef440caa0d55f6add3fdf23a55ebaa5e98ded541 (patch)
tree55496050bf317df093d86e69d22628457d4038e9 /lib/Parse/ParseOpenMP.cpp
parent36fa0d71c9d8086b7b53d0fa6eb60da8e3af11db (diff)
downloadclang-ef440caa0d55f6add3fdf23a55ebaa5e98ded541.tar.gz
[OPENMP50]Do not allow multiple same context traits in the same context
selector. According to OpenMP 5.0, 2.3.2 Context Selectors, Restrictions, each trait-selector-name can only be specified once. Added check for this restriction. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@374093 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseOpenMP.cpp')
-rw-r--r--lib/Parse/ParseOpenMP.cpp41
1 files changed, 29 insertions, 12 deletions
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index e487e0ab65..f667b83b58 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -815,7 +815,7 @@ static ExprResult parseContextScore(Parser &P) {
/// 'vendor' '(' [ 'score' '(' <score _expr> ')' ':' ] <vendor> { ',' <vendor> }
/// ')'
static void parseImplementationSelector(
- Parser &P, SourceLocation Loc,
+ Parser &P, SourceLocation Loc, llvm::StringMap<SourceLocation> &UsedCtx,
llvm::function_ref<void(SourceRange,
const Sema::OpenMPDeclareVariantCtsSelectorData &)>
Callback) {
@@ -832,6 +832,15 @@ static void parseImplementationSelector(
}
SmallString<16> Buffer;
StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
+ auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation());
+ if (!Res.second) {
+ // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions.
+ // Each trait-selector-name can only be specified once.
+ P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use)
+ << CtxSelectorName << "implementation";
+ P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
+ << CtxSelectorName;
+ }
OMPDeclareVariantAttr::CtxSelectorType CSKind =
OMPDeclareVariantAttr::CtxUnknown;
(void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorType(CtxSelectorName,
@@ -932,17 +941,25 @@ bool Parser::parseOpenMPContextSelectors(
OMPDeclareVariantAttr::CtxSetUnknown;
(void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorSetType(
CtxSelectorSetName, CSSKind);
- switch (CSSKind) {
- case OMPDeclareVariantAttr::CtxSetImplementation:
- parseImplementationSelector(*this, Loc, Callback);
- break;
- case OMPDeclareVariantAttr::CtxSetUnknown:
- // Skip until either '}', ')', or end of directive.
- while (!SkipUntil(tok::r_brace, tok::r_paren,
- tok::annot_pragma_openmp_end, StopBeforeMatch))
- ;
- break;
- }
+ llvm::StringMap<SourceLocation> UsedCtx;
+ do {
+ switch (CSSKind) {
+ case OMPDeclareVariantAttr::CtxSetImplementation:
+ parseImplementationSelector(*this, Loc, UsedCtx, Callback);
+ break;
+ case OMPDeclareVariantAttr::CtxSetUnknown:
+ // Skip until either '}', ')', or end of directive.
+ while (!SkipUntil(tok::r_brace, tok::r_paren,
+ tok::annot_pragma_openmp_end, StopBeforeMatch))
+ ;
+ break;
+ }
+ const Token PrevTok = Tok;
+ if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace))
+ Diag(Tok, diag::err_omp_expected_comma_brace)
+ << (PrevTok.isAnnotation() ? "context selector trait"
+ : PP.getSpelling(PrevTok));
+ } while (Tok.is(tok::identifier));
// Parse '}'.
(void)TBr.consumeClose();
}