[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.
llvm-svn: 374093
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index e487e0a..f667b83 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -815,7 +815,7 @@
/// '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 @@
}
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 @@
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();
}