summaryrefslogtreecommitdiffstats
path: root/clang/lib/ASTMatchers
diff options
context:
space:
mode:
authorStephen Kelly <steveire@gmail.com>2019-12-18 22:35:46 +0000
committerStephen Kelly <steveire@gmail.com>2019-12-27 15:25:57 +0000
commitf0722333dd167245eb3c2b4263529a1ce3679b5c (patch)
treee2bb3191dedf0f83247cbd6eedb7cf8af92d3f82 /clang/lib/ASTMatchers
parent2abda66848e5b7f502f978f030254118ec6751d6 (diff)
downloadbcm5719-llvm-f0722333dd167245eb3c2b4263529a1ce3679b5c.tar.gz
bcm5719-llvm-f0722333dd167245eb3c2b4263529a1ce3679b5c.zip
Allow newlines in AST Matchers in clang-query files
Reviewers: aaron.ballman Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D71842
Diffstat (limited to 'clang/lib/ASTMatchers')
-rw-r--r--clang/lib/ASTMatchers/Dynamic/Parser.cpp76
1 files changed, 55 insertions, 21 deletions
diff --git a/clang/lib/ASTMatchers/Dynamic/Parser.cpp b/clang/lib/ASTMatchers/Dynamic/Parser.cpp
index e3b00b46832..caa3a3bd095 100644
--- a/clang/lib/ASTMatchers/Dynamic/Parser.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Parser.cpp
@@ -38,6 +38,7 @@ struct Parser::TokenInfo {
/// Different possible tokens.
enum TokenKind {
TK_Eof,
+ TK_NewLine,
TK_OpenParen,
TK_CloseParen,
TK_Comma,
@@ -65,12 +66,12 @@ const char* const Parser::TokenInfo::ID_Bind = "bind";
/// Simple tokenizer for the parser.
class Parser::CodeTokenizer {
public:
- explicit CodeTokenizer(StringRef MatcherCode, Diagnostics *Error)
+ explicit CodeTokenizer(StringRef &MatcherCode, Diagnostics *Error)
: Code(MatcherCode), StartOfLine(MatcherCode), Error(Error) {
NextToken = getNextToken();
}
- CodeTokenizer(StringRef MatcherCode, Diagnostics *Error,
+ CodeTokenizer(StringRef &MatcherCode, Diagnostics *Error,
unsigned CodeCompletionOffset)
: Code(MatcherCode), StartOfLine(MatcherCode), Error(Error),
CodeCompletionLocation(MatcherCode.data() + CodeCompletionOffset) {
@@ -87,6 +88,19 @@ public:
return ThisToken;
}
+ TokenInfo SkipNewlines() {
+ while (NextToken.Kind == TokenInfo::TK_NewLine)
+ NextToken = getNextToken();
+ return NextToken;
+ }
+
+ TokenInfo consumeNextTokenIgnoreNewlines() {
+ SkipNewlines();
+ if (NextToken.Kind == TokenInfo::TK_Eof)
+ return NextToken;
+ return consumeNextToken();
+ }
+
TokenInfo::TokenKind nextTokenKind() const { return NextToken.Kind; }
private:
@@ -110,9 +124,8 @@ private:
switch (Code[0]) {
case '#':
- Result.Kind = TokenInfo::TK_Eof;
- Result.Text = "";
- return Result;
+ Code = Code.drop_until([](char c) { return c == '\n'; });
+ return getNextToken();
case ',':
Result.Kind = TokenInfo::TK_Comma;
Result.Text = Code.substr(0, 1);
@@ -123,6 +136,13 @@ private:
Result.Text = Code.substr(0, 1);
Code = Code.drop_front();
break;
+ case '\n':
+ ++Line;
+ StartOfLine = Code.drop_front();
+ Result.Kind = TokenInfo::TK_NewLine;
+ Result.Text = Code.substr(0, 1);
+ Code = Code.drop_front();
+ break;
case '(':
Result.Kind = TokenInfo::TK_OpenParen;
Result.Text = Code.substr(0, 1);
@@ -277,13 +297,10 @@ private:
/// Consume all leading whitespace from \c Code.
void consumeWhitespace() {
- while (!Code.empty() && isWhitespace(Code[0])) {
- if (Code[0] == '\n') {
- ++Line;
- StartOfLine = Code.drop_front();
- }
- Code = Code.drop_front();
- }
+ Code = Code.drop_while([](char c) {
+ // Don't trim newlines.
+ return StringRef(" \t\v\f\r").contains(c);
+ });
}
SourceLocation currentLocation() {
@@ -293,7 +310,7 @@ private:
return Location;
}
- StringRef Code;
+ StringRef &Code;
StringRef StartOfLine;
unsigned Line = 1;
Diagnostics *Error;
@@ -337,6 +354,13 @@ struct Parser::ScopedContextEntry {
bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
const TokenInfo NameToken = Tokenizer->consumeNextToken();
+ if (Tokenizer->nextTokenKind() == TokenInfo::TK_NewLine) {
+ Error->addError(Tokenizer->peekNextToken().Range,
+ Error->ET_ParserNoOpenParen)
+ << "NewLine";
+ return false;
+ }
+
if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
// Parse as a named value.
if (const VariantValue NamedValue =
@@ -368,6 +392,7 @@ bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
// unknown named value.
if ((Tokenizer->nextTokenKind() == TokenInfo::TK_Comma ||
Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen ||
+ Tokenizer->nextTokenKind() == TokenInfo::TK_NewLine ||
Tokenizer->nextTokenKind() == TokenInfo::TK_Eof) &&
!S->lookupMatcherCtor(NameToken.Text)) {
Error->addError(NameToken.Range, Error->ET_RegistryValueNotFound)
@@ -377,6 +402,8 @@ bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
// Otherwise, fallback to the matcher parser.
}
+ Tokenizer->SkipNewlines();
+
// Parse as a matcher expression.
return parseMatcherExpressionImpl(NameToken, Value);
}
@@ -392,8 +419,8 @@ bool Parser::parseBindID(std::string &BindID) {
}
const TokenInfo OpenToken = Tokenizer->consumeNextToken();
- const TokenInfo IDToken = Tokenizer->consumeNextToken();
- const TokenInfo CloseToken = Tokenizer->consumeNextToken();
+ const TokenInfo IDToken = Tokenizer->consumeNextTokenIgnoreNewlines();
+ const TokenInfo CloseToken = Tokenizer->consumeNextTokenIgnoreNewlines();
// TODO: We could use different error codes for each/some to be more
// explicit about the syntax error.
@@ -443,6 +470,8 @@ bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken,
std::vector<ParserValue> Args;
TokenInfo EndToken;
+ Tokenizer->SkipNewlines();
+
{
ScopedContextEntry SCE(this, Ctor ? *Ctor : nullptr);
@@ -466,12 +495,14 @@ bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken,
NameToken.Text, NameToken.Range,
Args.size() + 1);
ParserValue ArgValue;
+ Tokenizer->SkipNewlines();
ArgValue.Text = Tokenizer->peekNextToken().Text;
ArgValue.Range = Tokenizer->peekNextToken().Range;
if (!parseExpressionImpl(&ArgValue.Value)) {
return false;
}
+ Tokenizer->SkipNewlines();
Args.push_back(ArgValue);
SCE.nextArg();
}
@@ -531,7 +562,7 @@ std::vector<MatcherCompletion> Parser::getNamedValueCompletions(
}
void Parser::addExpressionCompletions() {
- const TokenInfo CompToken = Tokenizer->consumeNextToken();
+ const TokenInfo CompToken = Tokenizer->consumeNextTokenIgnoreNewlines();
assert(CompToken.Kind == TokenInfo::TK_CodeCompletion);
// We cannot complete code if there is an invalid element on the context
@@ -575,7 +606,9 @@ bool Parser::parseExpressionImpl(VariantValue *Value) {
case TokenInfo::TK_Error:
// This error was already reported by the tokenizer.
return false;
-
+ case TokenInfo::TK_NewLine:
+ llvm_unreachable("Newline should never be found here");
+ return false;
case TokenInfo::TK_OpenParen:
case TokenInfo::TK_CloseParen:
case TokenInfo::TK_Comma:
@@ -624,13 +657,14 @@ std::vector<MatcherCompletion> Parser::RegistrySema::getMatcherCompletions(
return Registry::getMatcherCompletions(AcceptedTypes);
}
-bool Parser::parseExpression(StringRef Code, Sema *S,
+bool Parser::parseExpression(StringRef &Code, Sema *S,
const NamedValueMap *NamedValues,
VariantValue *Value, Diagnostics *Error) {
CodeTokenizer Tokenizer(Code, Error);
if (!Parser(&Tokenizer, S, NamedValues, Error).parseExpressionImpl(Value))
return false;
- if (Tokenizer.peekNextToken().Kind != TokenInfo::TK_Eof) {
+ auto NT = Tokenizer.peekNextToken();
+ if (NT.Kind != TokenInfo::TK_Eof && NT.Kind != TokenInfo::TK_NewLine) {
Error->addError(Tokenizer.peekNextToken().Range,
Error->ET_ParserTrailingCode);
return false;
@@ -639,7 +673,7 @@ bool Parser::parseExpression(StringRef Code, Sema *S,
}
std::vector<MatcherCompletion>
-Parser::completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S,
+Parser::completeExpression(StringRef &Code, unsigned CompletionOffset, Sema *S,
const NamedValueMap *NamedValues) {
Diagnostics Error;
CodeTokenizer Tokenizer(Code, &Error, CompletionOffset);
@@ -659,7 +693,7 @@ Parser::completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S,
}
llvm::Optional<DynTypedMatcher>
-Parser::parseMatcherExpression(StringRef Code, Sema *S,
+Parser::parseMatcherExpression(StringRef &Code, Sema *S,
const NamedValueMap *NamedValues,
Diagnostics *Error) {
VariantValue Value;
OpenPOWER on IntegriCloud