forked from OSchip/llvm-project
Enable ActOnIdExpression to use delayed typo correction for non-C++ code
when calling DiagnoseEmptyLookup. llvm-svn: 222551
This commit is contained in:
parent
4c3ffc4fef
commit
1586782767
|
@ -5724,7 +5724,8 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
|
|||
} else {
|
||||
EnterExpressionEvaluationContext Unevaluated(Actions,
|
||||
Sema::ConstantEvaluated);
|
||||
NumElements = ParseAssignmentExpression();
|
||||
NumElements =
|
||||
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
|
||||
}
|
||||
} else {
|
||||
if (StaticLoc.isValid()) {
|
||||
|
|
|
@ -910,6 +910,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
|||
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(SmallVectorImpl<Expr*> &Exprs,
|
|||
}
|
||||
|
||||
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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -2350,7 +2350,7 @@ ExprResult Parser::ParseObjCMessageExpression() {
|
|||
}
|
||||
|
||||
// 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(SourceLocation LBracLoc,
|
|||
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) <<
|
||||
|
|
|
@ -715,7 +715,8 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
|
|||
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 {
|
||||
|
|
|
@ -774,7 +774,7 @@ bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
|
|||
// 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);
|
||||
|
|
|
@ -2122,9 +2122,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
|
|||
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(Sema &S, MultiExprArg args) {
|
|||
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(ExprResult &Cond, ExprResult &LHS,
|
|||
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(Expr *LHSExpr, ExprResult &RHS,
|
|||
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(SourceLocation OpLoc,
|
|||
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(Sema &S, Expr *E) {
|
|||
/// 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;
|
||||
|
||||
|
|
|
@ -1676,11 +1676,16 @@ Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) {
|
|||
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();
|
||||
|
|
|
@ -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'{{$}}}}
|
Loading…
Reference in New Issue