aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseExpr.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-04-24 05:37:28 +0000
committerDouglas Gregor <dgregor@apple.com>2011-04-24 05:37:28 +0000
commit312eadb832cab4497a069409954500d8192b8f0d (patch)
treef919e5f5b0f8f0e2092ee948b86f92a7171697a2 /lib/Parse/ParseExpr.cpp
parent1b6005285e234bc30698917b2d3abb2f1f98bc77 (diff)
Implement a new identifier-classification scheme where Sema
performs name lookup for an identifier and resolves it to a type/expression/template/etc. in the same step. This scheme is intended to improve both performance (by reducing the number of redundant name lookups for a given identifier token) and error recovery (by giving Sema a chance to correct type names before the parser has decided that the identifier isn't a type name). For example, this allows us to properly typo-correct type names at the beginning of a statement: t.c:6:3: error: use of undeclared identifier 'integer'; did you mean 'Integer'? integer *i = 0; ^~~~~~~ Integer t.c:1:13: note: 'Integer' declared here typedef int Integer; ^ Previously, we wouldn't give a Fix-It because the typo correction occurred after the parser had checked whether "integer" was a type name (via Sema::getTypeName(), which isn't allowed to typo-correct) and therefore decided to parse "integer * i = 0" as an expression. By typo-correcting earlier, we typo-correct to the type name Integer and parse this as a declaration. Moreover, in this context, we can also typo-correct identifiers to keywords, e.g., t.c:7:3: error: use of undeclared identifier 'vid'; did you mean 'void'? vid *p = i; ^~~ void and recover appropriately. Note that this is very much a work-in-progress. The new Sema::ClassifyName is only used for expression-or-declaration disambiguation in C at the statement level. The next steps will be to make this work for the same disambiguation in C++ (where functional-style casts make some trouble), then push it further into the parser to eliminate more redundant name lookups. Fixes <rdar://problem/7963833> for C and starts us down the path of <rdar://problem/8172000>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130082 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseExpr.cpp')
-rw-r--r--lib/Parse/ParseExpr.cpp28
1 files changed, 20 insertions, 8 deletions
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 0ad153fc57..cd8f9c53f7 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -175,8 +175,10 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
/// assignment-expression ...[opt]
/// expression ',' assignment-expression ...[opt]
///
-ExprResult Parser::ParseExpression() {
- ExprResult LHS(ParseAssignmentExpression());
+/// \param Primary if non-empty, an already-parsed expression that will be used
+/// as the first primary expression.
+ExprResult Parser::ParseExpression(ExprResult Primary) {
+ ExprResult LHS(ParseAssignmentExpression(Primary));
return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
}
@@ -213,16 +215,26 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
/// ParseAssignmentExpression - Parse an expr that doesn't include commas.
///
-ExprResult Parser::ParseAssignmentExpression() {
+/// \param Primary if non-empty, an already-parsed expression that will be used
+/// as the first primary expression.
+ExprResult Parser::ParseAssignmentExpression(ExprResult Primary) {
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
+ if (Primary.isUsable())
+ Actions.CodeCompletePostfixExpression(getCurScope(), Primary);
+ else
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
ConsumeCodeCompletionToken();
}
- if (Tok.is(tok::kw_throw))
+ if (!Primary.isUsable() && Tok.is(tok::kw_throw))
return ParseThrowExpression();
- ExprResult LHS(ParseCastExpression(false));
+ ExprResult LHS;
+ if (Primary.get() || Primary.isInvalid())
+ LHS = ParsePostfixExpressionSuffix(Primary);
+ else
+ LHS = ParseCastExpression(false, false, ParsedType());
+
return ParseRHSOfBinaryExpression(move(LHS), prec::Assignment);
}
@@ -415,8 +427,8 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
/// due to member pointers.
///
ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
- bool isAddressOfOperand,
- ParsedType TypeOfCast) {
+ bool isAddressOfOperand,
+ ParsedType TypeOfCast) {
bool NotCastExpr;
ExprResult Res = ParseCastExpression(isUnaryExpression,
isAddressOfOperand,