OpenMP threadprivate with qualified names.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181683 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index 507a6b1..e192ae2 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -12,8 +12,10 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTConsumer.h"
-#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/Scope.h"
+#include "llvm/ADT/PointerIntPair.h"
#include "RAIIObjectsForParser.h"
using namespace clang;
@@ -21,22 +23,24 @@
// OpenMP declarative directives.
//===----------------------------------------------------------------------===//
-/// \brief Parses OpenMP declarative directive
-/// threadprivate-directive
-/// annot_pragma_openmp threadprivate simple-variable-list
+/// \brief Parsing of declarative OpenMP directives.
+///
+/// threadprivate-directive:
+/// annot_pragma_openmp 'threadprivate' simple-variable-list
///
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
SourceLocation Loc = ConsumeToken();
- SmallVector<DeclarationNameInfo, 5> Identifiers;
- OpenMPDirectiveKind Kind = Tok.isAnnotation() ?
- OMPD_unknown :
- getOpenMPDirectiveKind(PP.getSpelling(Tok));
- switch(Kind) {
+ SmallVector<Expr *, 5> Identifiers;
+ OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
+ OMPD_unknown :
+ getOpenMPDirectiveKind(PP.getSpelling(Tok));
+
+ switch (DKind) {
case OMPD_threadprivate:
ConsumeToken();
- if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers)) {
+ if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
// The last seen token is annot_pragma_openmp_end - need to check for
// extra tokens.
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
@@ -44,9 +48,9 @@
<< getOpenMPDirectiveName(OMPD_threadprivate);
SkipUntil(tok::annot_pragma_openmp_end, false, true);
}
+ // Skip the last annot_pragma_openmp_end.
ConsumeToken();
return Actions.ActOnOpenMPThreadprivateDirective(Loc,
- getCurScope(),
Identifiers);
}
break;
@@ -55,7 +59,7 @@
break;
default:
Diag(Tok, diag::err_omp_unexpected_directive)
- << getOpenMPDirectiveName(Kind);
+ << getOpenMPDirectiveName(DKind);
break;
}
SkipUntil(tok::annot_pragma_openmp_end, false);
@@ -63,56 +67,69 @@
}
/// \brief Parses list of simple variables for '#pragma omp threadprivate'
-/// directive
-/// simple-variable-list:
-/// ( unqualified-id {, unqualified-id} ) annot_pragma_openmp_end
+/// directive.
///
-bool Parser::ParseOpenMPSimpleVarList(
- OpenMPDirectiveKind Kind,
- SmallVectorImpl<DeclarationNameInfo> &IdList) {
+/// simple-variable-list:
+/// '(' id-expression {, id-expression} ')'
+///
+bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
+ SmallVectorImpl<Expr *> &VarList,
+ bool AllowScopeSpecifier) {
+ VarList.clear();
// Parse '('.
- bool IsCorrect = true;
- BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen_after,
- getOpenMPDirectiveName(Kind))) {
- SkipUntil(tok::annot_pragma_openmp_end, false, true);
- return false;
- }
+ BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+ bool LParen = !T.expectAndConsume(diag::err_expected_lparen_after,
+ getOpenMPDirectiveName(Kind));
+ bool IsCorrect = LParen;
+ bool NoIdentIsFound = true;
// Read tokens while ')' or annot_pragma_openmp_end is not found.
- do {
+ while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
UnqualifiedId Name;
// Read var name.
Token PrevTok = Tok;
+ NoIdentIsFound = false;
- if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
- TemplateKWLoc, Name)) {
+ if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
IsCorrect = false;
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
false, true);
- }
- else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
- Tok.isNot(tok::annot_pragma_openmp_end)) {
+ } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
+ TemplateKWLoc, Name)) {
IsCorrect = false;
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
false, true);
- Diag(PrevTok.getLocation(), diag::err_expected_unqualified_id)
- << getLangOpts().CPlusPlus
+ } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
+ Tok.isNot(tok::annot_pragma_openmp_end)) {
+ IsCorrect = false;
+ SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+ false, true);
+ Diag(PrevTok.getLocation(), diag::err_expected_ident)
<< SourceRange(PrevTok.getLocation(), PrevTokLocation);
} else {
- IdList.push_back(Actions.GetNameFromUnqualifiedId(Name));
+ DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
+ ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS,
+ NameInfo);
+ if (Res.isUsable())
+ VarList.push_back(Res.take());
}
// Consume ','.
if (Tok.is(tok::comma)) {
ConsumeToken();
}
- } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
-
- if (IsCorrect || Tok.is(tok::r_paren)) {
- IsCorrect = !T.consumeClose() && IsCorrect;
}
- return !IsCorrect && IdList.empty();
+ if (NoIdentIsFound) {
+ Diag(Tok, diag::err_expected_ident);
+ IsCorrect = false;
+ }
+
+ // Parse ')'.
+ IsCorrect = ((LParen || Tok.is(tok::r_paren)) && !T.consumeClose())
+ && IsCorrect;
+
+ return !IsCorrect && VarList.empty();
}
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 2117df4..a5371f9 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -1897,7 +1897,7 @@
P.Diag(P.Tok, diag::err_bracket_depth_exceeded)
<< P.getLangOpts().BracketDepth;
P.Diag(P.Tok, diag::note_bracket_depth);
- P.SkipUntil(tok::eof);
+ P.SkipUntil(tok::eof, FinalToken);
return true;
}
@@ -1927,7 +1927,8 @@
}
P.Diag(P.Tok, DID);
P.Diag(LOpen, diag::note_matching) << LHSName;
- if (P.SkipUntil(Close, /*StopAtSemi*/ true, /*DontConsume*/ true))
+ if (P.SkipUntil(Close, FinalToken, /*StopAtSemi*/ true, /*DontConsume*/ true)
+ && P.Tok.is(Close))
LClose = P.ConsumeAnyToken();
return true;
}
diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h
index 213950a..f68a2e0 100644
--- a/lib/Parse/RAIIObjectsForParser.h
+++ b/lib/Parse/RAIIObjectsForParser.h
@@ -358,7 +358,7 @@
/// pair, such as braces { ... } or parentheses ( ... ).
class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
Parser& P;
- tok::TokenKind Kind, Close;
+ tok::TokenKind Kind, Close, FinalToken;
SourceLocation (Parser::*Consumer)();
SourceLocation LOpen, LClose;
@@ -377,9 +377,10 @@
bool diagnoseMissingClose();
public:
- BalancedDelimiterTracker(Parser& p, tok::TokenKind k)
+ BalancedDelimiterTracker(Parser& p, tok::TokenKind k,
+ tok::TokenKind FinalToken = tok::semi)
: GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
- P(p), Kind(k)
+ P(p), Kind(k), FinalToken(FinalToken)
{
switch (Kind) {
default: llvm_unreachable("Unexpected balanced token");