r222551 - Enable ActOnIdExpression to use delayed typo correction for non-C++ code
Kaelyn Takata
rikka at google.com
Fri Nov 21 10:48:04 PST 2014
Author: rikka
Date: Fri Nov 21 12:48:04 2014
New Revision: 222551
URL: http://llvm.org/viewvc/llvm-project?rev=222551&view=rev
Log:
Enable ActOnIdExpression to use delayed typo correction for non-C++ code
when calling DiagnoseEmptyLookup.
Added:
cfe/trunk/test/Sema/typo-correction.c
Modified:
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Parse/ParseInit.cpp
cfe/trunk/lib/Parse/ParseObjc.cpp
cfe/trunk/lib/Parse/ParseOpenMP.cpp
cfe/trunk/lib/Parse/ParseStmtAsm.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaStmt.cpp
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=222551&r1=222550&r2=222551&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Nov 21 12:48:04 2014
@@ -5724,7 +5724,8 @@ void Parser::ParseBracketDeclarator(Decl
} else {
EnterExpressionEvaluationContext Unevaluated(Actions,
Sema::ConstantEvaluated);
- NumElements = ParseAssignmentExpression();
+ NumElements =
+ Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
}
} else {
if (StaticLoc.isValid()) {
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=222551&r1=222550&r2=222551&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Fri Nov 21 12:48:04 2014
@@ -910,6 +910,7 @@ ExprResult Parser::ParseCastExpression(b
auto Validator = llvm::make_unique<CastExpressionIdValidator>(
isTypeCast != NotTypeCast, isTypeCast != IsTypeCast);
Validator->IsAddressOfOperand = isAddressOfOperand;
+ Validator->WantRemainingKeywords = Tok.isNot(tok::r_paren);
Name.setIdentifier(&II, ILoc);
Res = Actions.ActOnIdExpression(
getCurScope(), ScopeSpec, TemplateKWLoc, Name, Tok.is(tok::l_paren),
@@ -2513,10 +2514,19 @@ bool Parser::ParseExpressionList(SmallVe
}
if (Tok.isNot(tok::comma))
- return SawError;
+ break;
// Move to the next argument, remember where the comma was.
CommaLocs.push_back(ConsumeToken());
}
+ if (SawError) {
+ // Ensure typos get diagnosed when errors were encountered while parsing the
+ // expression list.
+ for (auto &E : Exprs) {
+ ExprResult Expr = Actions.CorrectDelayedTyposInExpr(E);
+ if (Expr.isUsable()) E = Expr.get();
+ }
+ }
+ return SawError;
}
/// ParseSimpleExpressionList - A simple comma-separated list of expressions,
Modified: cfe/trunk/lib/Parse/ParseInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseInit.cpp?rev=222551&r1=222550&r2=222551&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseInit.cpp (original)
+++ cfe/trunk/lib/Parse/ParseInit.cpp Fri Nov 21 12:48:04 2014
@@ -423,9 +423,11 @@ ExprResult Parser::ParseBraceInitializer
if (Tok.is(tok::ellipsis))
SubElt = Actions.ActOnPackExpansion(SubElt.get(), ConsumeToken());
-
+
+ SubElt = Actions.CorrectDelayedTyposInExpr(SubElt.get());
+
// If we couldn't parse the subelement, bail out.
- if (!SubElt.isInvalid()) {
+ if (SubElt.isUsable()) {
InitExprs.push_back(SubElt.get());
} else {
InitExprsOk = false;
Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=222551&r1=222550&r2=222551&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Fri Nov 21 12:48:04 2014
@@ -2350,7 +2350,7 @@ ExprResult Parser::ParseObjCMessageExpre
}
// Otherwise, an arbitrary expression can be the receiver of a send.
- ExprResult Res(ParseExpression());
+ ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression());
if (Res.isInvalid()) {
SkipUntil(tok::r_square, StopAtSemi);
return Res;
@@ -2509,6 +2509,8 @@ Parser::ParseObjCMessageExpressionBody(S
SourceLocation commaLoc = ConsumeToken(); // Eat the ','.
/// Parse the expression after ','
ExprResult Res(ParseAssignmentExpression());
+ if (Tok.is(tok::colon))
+ Res = Actions.CorrectDelayedTyposInExpr(Res);
if (Res.isInvalid()) {
if (Tok.is(tok::colon)) {
Diag(commaLoc, diag::note_extra_comma_message_arg) <<
Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=222551&r1=222550&r2=222551&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)
+++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Fri Nov 21 12:48:04 2014
@@ -715,7 +715,8 @@ OMPClause *Parser::ParseOpenMPVarListCla
Tok.isNot(tok::annot_pragma_openmp_end))) {
ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
// Parse variable
- ExprResult VarExpr = ParseAssignmentExpression();
+ ExprResult VarExpr =
+ Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
if (VarExpr.isUsable()) {
Vars.push_back(VarExpr.get());
} else {
Modified: cfe/trunk/lib/Parse/ParseStmtAsm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmtAsm.cpp?rev=222551&r1=222550&r2=222551&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmtAsm.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmtAsm.cpp Fri Nov 21 12:48:04 2014
@@ -774,7 +774,7 @@ bool Parser::ParseAsmOperandsOpt(SmallVe
// Read the parenthesized expression.
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
- ExprResult Res(ParseExpression());
+ ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression());
T.consumeClose();
if (Res.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=222551&r1=222550&r2=222551&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Nov 21 12:48:04 2014
@@ -2122,9 +2122,9 @@ Sema::ActOnIdExpression(Scope *S, CXXSco
if (SS.isValid())
CCC->setTypoNNS(SS.getScopeRep());
}
- if (DiagnoseEmptyLookup(
- S, SS, R, CCC ? std::move(CCC) : std::move(DefaultValidator),
- nullptr, None, getLangOpts().CPlusPlus ? &TE : nullptr)) {
+ if (DiagnoseEmptyLookup(S, SS, R,
+ CCC ? std::move(CCC) : std::move(DefaultValidator),
+ nullptr, None, &TE)) {
if (TE && KeywordReplacement) {
auto &State = getTypoExprState(TE);
auto BestTC = State.Consumer->getNextCorrection();
@@ -4541,6 +4541,8 @@ static bool checkArgsForPlaceholders(Sem
ExprResult result = S.CheckPlaceholderExpr(args[i]);
if (result.isInvalid()) hasInvalid = true;
else args[i] = result.get();
+ } else if (hasInvalid) {
+ (void)S.CorrectDelayedTyposInExpr(args[i]);
}
}
return hasInvalid;
@@ -5763,6 +5765,15 @@ QualType Sema::CheckConditionalOperands(
ExprObjectKind &OK,
SourceLocation QuestionLoc) {
+ if (!getLangOpts().CPlusPlus) {
+ // C cannot handle TypoExpr nodes on either side of a binop because it
+ // doesn't handle dependent types properly, so make sure any TypoExprs have
+ // been dealt with before checking the operands.
+ ExprResult CondResult = CorrectDelayedTyposInExpr(Cond);
+ if (!CondResult.isUsable()) return QualType();
+ Cond = CondResult;
+ }
+
ExprResult LHSResult = CheckPlaceholderExpr(LHS.get());
if (!LHSResult.isUsable()) return QualType();
LHS = LHSResult;
@@ -8703,17 +8714,6 @@ QualType Sema::CheckAssignmentOperands(E
QualType CompoundType) {
assert(!LHSExpr->hasPlaceholderType(BuiltinType::PseudoObject));
- if (!getLangOpts().CPlusPlus) {
- // C cannot handle TypoExpr nodes on either side of n assignment because it
- // doesn't handle dependent types properly, so make sure any TypoExprs have
- // been dealt with before checking the operands.
- ExprResult Res = CorrectDelayedTyposInExpr(LHSExpr);
- Expr *NewLHS = Res.isInvalid() ? LHSExpr : Res.get();
- Res = CorrectDelayedTyposInExpr(RHS);
- if (!Res.isInvalid() && (Res.get() != RHS.get() || NewLHS != LHSExpr))
- return CheckAssignmentOperands(NewLHS, Res, Loc, CompoundType);
- }
-
// Verify that LHS is a modifiable lvalue, and emit error if not.
if (CheckForModifiableLvalue(LHSExpr, Loc, *this))
return QualType();
@@ -9447,6 +9447,16 @@ ExprResult Sema::CreateBuiltinBinOp(Sour
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
+ if (!getLangOpts().CPlusPlus) {
+ // C cannot handle TypoExpr nodes on either side of a binop because it
+ // doesn't handle dependent types properly, so make sure any TypoExprs have
+ // been dealt with before checking the operands.
+ LHS = CorrectDelayedTyposInExpr(LHSExpr);
+ RHS = CorrectDelayedTyposInExpr(RHSExpr);
+ if (!LHS.isUsable() || !RHS.isUsable())
+ return ExprError();
+ }
+
switch (Opc) {
case BO_Assign:
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType());
@@ -13619,6 +13629,15 @@ static ExprResult diagnoseUnknownAnyExpr
/// Check for operands with placeholder types and complain if found.
/// Returns true if there was an error and no recovery was possible.
ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
+ if (!getLangOpts().CPlusPlus) {
+ // C cannot handle TypoExpr nodes on either side of a binop because it
+ // doesn't handle dependent types properly, so make sure any TypoExprs have
+ // been dealt with before checking the operands.
+ ExprResult Result = CorrectDelayedTyposInExpr(E);
+ if (!Result.isUsable()) return ExprError();
+ E = Result.get();
+ }
+
const BuiltinType *placeholderType = E->getType()->getAsPlaceholderType();
if (!placeholderType) return E;
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=222551&r1=222550&r2=222551&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Fri Nov 21 12:48:04 2014
@@ -1676,11 +1676,16 @@ Sema::CheckObjCForCollectionOperand(Sour
if (!collection)
return ExprError();
+ ExprResult result = CorrectDelayedTyposInExpr(collection);
+ if (!result.isUsable())
+ return ExprError();
+ collection = result.get();
+
// Bail out early if we've got a type-dependent expression.
if (collection->isTypeDependent()) return collection;
// Perform normal l-value conversion.
- ExprResult result = DefaultFunctionArrayLvalueConversion(collection);
+ result = DefaultFunctionArrayLvalueConversion(collection);
if (result.isInvalid())
return ExprError();
collection = result.get();
Added: cfe/trunk/test/Sema/typo-correction.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/typo-correction.c?rev=222551&view=auto
==============================================================================
--- cfe/trunk/test/Sema/typo-correction.c (added)
+++ cfe/trunk/test/Sema/typo-correction.c Fri Nov 21 12:48:04 2014
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+//
+// This file contains typo correction tests which hit different code paths in C
+// than in C++ and may exhibit different behavior as a result.
+
+__typeof__(struct F*) var[invalid]; // expected-error-re {{use of undeclared identifier 'invalid'{{$}}}}
More information about the cfe-commits
mailing list