Remove delayed typo expressions (#143423)

This removes the delayed typo correction functionality from Clang
(regular typo correction still remains) due to fragility of the
solution.

An RFC was posted here:
https://discourse.llvm.org/t/rfc-removing-support-for-delayed-typo-correction/86631
and while that RFC was asking for folks to consider stepping up to be
maintainers, and we did have a few new contributors show some interest,
experiments show that it's likely worth it to remove this functionality
entirely and focus efforts on improving regular typo correction.

This removal fixes ~20 open issues (quite possibly more), improves
compile time performance by roughly .3-.4%
(https://llvm-compile-time-tracker.com/?config=Overview&stat=instructions%3Au&remote=AaronBallman&sortBy=date),
and does not appear to regress diagnostic behavior in a way we wouldn't
find acceptable.

Fixes #142457
Fixes #139913
Fixes #138850
Fixes #137867
Fixes #137860
Fixes #107840
Fixes #93308
Fixes #69470
Fixes #59391
Fixes #58172
Fixes #46215
Fixes #45915
Fixes #45891
Fixes #44490
Fixes #36703
Fixes #32903
Fixes #23312
Fixes #69874
This commit is contained in:
Aaron Ballman 2025-06-13 06:45:40 -04:00 committed by GitHub
parent 541e5118ce
commit 9eef4d1c5f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
116 changed files with 438 additions and 2147 deletions

View File

@ -974,7 +974,7 @@ class Foo final {})cpp";
HI.Name = "abc";
HI.Kind = index::SymbolKind::Variable;
HI.NamespaceScope = "";
HI.Definition = "int abc = <recovery - expr>()";
HI.Definition = "int abc";
HI.Type = "int";
HI.AccessSpecifier = "public";
}},

View File

@ -622,6 +622,14 @@ Improvements to Clang's diagnostics
- Improved the FixIts for unused lambda captures.
- Delayed typo correction was removed from the compiler; immediate typo
correction behavior remains the same. Delayed typo correction facilities were
fragile and unmaintained, and the removal closed the following issues:
#GH142457, #GH139913, #GH138850, #GH137867, #GH137860, #GH107840, #GH93308,
#GH69470, #GH59391, #GH58172, #GH46215, #GH45915, #GH45891, #GH44490,
#GH36703, #GH32903, #GH23312, #GH69874.
Improvements to Clang's time-trace
----------------------------------

View File

@ -240,8 +240,7 @@ public:
return static_cast<bool>(getDependence() & ExprDependence::UnexpandedPack);
}
/// Whether this expression contains subexpressions which had errors, e.g. a
/// TypoExpr.
/// Whether this expression contains subexpressions which had errors.
bool containsErrors() const {
return static_cast<bool>(getDependence() & ExprDependence::Error);
}
@ -6965,36 +6964,6 @@ public:
}
};
/// TypoExpr - Internal placeholder for expressions where typo correction
/// still needs to be performed and/or an error diagnostic emitted.
class TypoExpr : public Expr {
// The location for the typo name.
SourceLocation TypoLoc;
public:
TypoExpr(QualType T, SourceLocation TypoLoc)
: Expr(TypoExprClass, T, VK_LValue, OK_Ordinary), TypoLoc(TypoLoc) {
assert(T->isDependentType() && "TypoExpr given a non-dependent type");
setDependence(ExprDependence::TypeValueInstantiation |
ExprDependence::Error);
}
child_range children() {
return child_range(child_iterator(), child_iterator());
}
const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}
SourceLocation getBeginLoc() const LLVM_READONLY { return TypoLoc; }
SourceLocation getEndLoc() const LLVM_READONLY { return TypoLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == TypoExprClass;
}
};
/// This class represents BOTH the OpenMP Array Section and OpenACC 'subarray',
/// with a boolean differentiator.
/// OpenMP 5.0 [2.1.5, Array Sections].

View File

@ -2956,7 +2956,6 @@ DEF_TRAVERSE_STMT(CXXRewrittenBinaryOperator, {
}
})
DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
DEF_TRAVERSE_STMT(TypoExpr, {})
DEF_TRAVERSE_STMT(RecoveryExpr, {})
DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})

View File

@ -202,7 +202,6 @@ def ShuffleVectorExpr : StmtNode<Expr>;
def ConvertVectorExpr : StmtNode<Expr>;
def BlockExpr : StmtNode<Expr>;
def OpaqueValueExpr : StmtNode<Expr>;
def TypoExpr : StmtNode<Expr>;
def RecoveryExpr : StmtNode<Expr>;
def BuiltinBitCastExpr : StmtNode<ExplicitCastExpr>;
def EmbedExpr : StmtNode<Expr>;

View File

@ -4169,8 +4169,7 @@ private:
bool ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
llvm::function_ref<void()> ExpressionStarts =
llvm::function_ref<void()>(),
bool FailImmediatelyOnInvalidExpr = false,
bool EarlyTypoCorrection = false);
bool FailImmediatelyOnInvalidExpr = false);
/// ParseSimpleExpressionList - A simple comma-separated list of expressions,
/// used for misc language extensions.

View File

@ -6713,10 +6713,6 @@ public:
/// this expression evaluation context.
unsigned NumCleanupObjects;
/// The number of typos encountered during this expression evaluation
/// context (i.e. the number of TypoExprs created).
unsigned NumTypos;
MaybeODRUseExprSet SavedMaybeODRUseExprs;
/// The lambdas that are present within this context, if it
@ -6813,7 +6809,7 @@ public:
Decl *ManglingContextDecl,
ExpressionKind ExprContext)
: Context(Context), ParentCleanup(ParentCleanup),
NumCleanupObjects(NumCleanupObjects), NumTypos(0),
NumCleanupObjects(NumCleanupObjects),
ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext),
InDiscardedStatement(false), InImmediateFunctionContext(false),
InImmediateEscalatingFunctionContext(false) {}
@ -7146,8 +7142,7 @@ public:
CorrectionCandidateCallback &CCC,
TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
ArrayRef<Expr *> Args = {},
DeclContext *LookupCtx = nullptr,
TypoExpr **Out = nullptr);
DeclContext *LookupCtx = nullptr);
/// If \p D cannot be odr-used in the current expression evaluation context,
/// return a reason explaining why. Otherwise, return NOUR_None.
@ -8748,40 +8743,6 @@ public:
ExprResult CheckUnevaluatedOperand(Expr *E);
/// Process any TypoExprs in the given Expr and its children,
/// generating diagnostics as appropriate and returning a new Expr if there
/// were typos that were all successfully corrected and ExprError if one or
/// more typos could not be corrected.
///
/// \param E The Expr to check for TypoExprs.
///
/// \param InitDecl A VarDecl to avoid because the Expr being corrected is its
/// initializer.
///
/// \param RecoverUncorrectedTypos If true, when typo correction fails, it
/// will rebuild the given Expr with all TypoExprs degraded to RecoveryExprs.
///
/// \param Filter A function applied to a newly rebuilt Expr to determine if
/// it is an acceptable/usable result from a single combination of typo
/// corrections. As long as the filter returns ExprError, different
/// combinations of corrections will be tried until all are exhausted.
ExprResult CorrectDelayedTyposInExpr(
Expr *E, VarDecl *InitDecl = nullptr,
bool RecoverUncorrectedTypos = false,
llvm::function_ref<ExprResult(Expr *)> Filter =
[](Expr *E) -> ExprResult { return E; });
ExprResult CorrectDelayedTyposInExpr(
ExprResult ER, VarDecl *InitDecl = nullptr,
bool RecoverUncorrectedTypos = false,
llvm::function_ref<ExprResult(Expr *)> Filter =
[](Expr *E) -> ExprResult { return E; }) {
return ER.isInvalid()
? ER
: CorrectDelayedTyposInExpr(ER.get(), InitDecl,
RecoverUncorrectedTypos, Filter);
}
IfExistsResult
CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS,
const DeclarationNameInfo &TargetNameInfo);
@ -9283,12 +9244,6 @@ public:
/// for C++ records.
llvm::FoldingSet<SpecialMemberOverloadResultEntry> SpecialMemberCache;
/// Holds TypoExprs that are created from `createDelayedTypo`. This is used by
/// `TransformTypos` in order to keep track of any TypoExprs that are created
/// recursively during typo correction and wipe them away if the correction
/// fails.
llvm::SmallVector<TypoExpr *, 2> TypoExprs;
enum class AcceptableKind { Visible, Reachable };
// Members have to be NamespaceDecl* or TranslationUnitDecl*.
@ -9376,10 +9331,6 @@ public:
bool VolatileArg, bool RValueThis, bool ConstThis,
bool VolatileThis);
typedef std::function<void(const TypoCorrection &)> TypoDiagnosticGenerator;
typedef std::function<ExprResult(Sema &, TypoExpr *, TypoCorrection)>
TypoRecoveryCallback;
RedeclarationKind forRedeclarationInCurContext() const;
/// Look up a name, looking for a single declaration. Return
@ -9733,51 +9684,6 @@ public:
const ObjCObjectPointerType *OPT = nullptr,
bool RecordFailure = true);
/// Try to "correct" a typo in the source code by finding
/// visible declarations whose names are similar to the name that was
/// present in the source code.
///
/// \param TypoName the \c DeclarationNameInfo structure that contains
/// the name that was present in the source code along with its location.
///
/// \param LookupKind the name-lookup criteria used to search for the name.
///
/// \param S the scope in which name lookup occurs.
///
/// \param SS the nested-name-specifier that precedes the name we're
/// looking for, if present.
///
/// \param CCC A CorrectionCandidateCallback object that provides further
/// validation of typo correction candidates. It also provides flags for
/// determining the set of keywords permitted.
///
/// \param TDG A TypoDiagnosticGenerator functor that will be used to print
/// diagnostics when the actual typo correction is attempted.
///
/// \param TRC A TypoRecoveryCallback functor that will be used to build an
/// Expr from a typo correction candidate.
///
/// \param MemberContext if non-NULL, the context in which to look for
/// a member access expression.
///
/// \param EnteringContext whether we're entering the context described by
/// the nested-name-specifier SS.
///
/// \param OPT when non-NULL, the search for visible declarations will
/// also walk the protocols in the qualified interfaces of \p OPT.
///
/// \returns a new \c TypoExpr that will later be replaced in the AST with an
/// Expr representing the result of performing typo correction, or nullptr if
/// typo correction is not possible. If nullptr is returned, no diagnostics
/// will be emitted and it is the responsibility of the caller to emit any
/// that are needed.
TypoExpr *CorrectTypoDelayed(
const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind,
Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC,
CorrectTypoKind Mode, DeclContext *MemberContext = nullptr,
bool EnteringContext = false, const ObjCObjectPointerType *OPT = nullptr);
/// Kinds of missing import. Note, the values of these enumerators correspond
/// to %select values in diagnostics.
enum class MissingImportKind {
@ -9796,20 +9702,6 @@ public:
SourceLocation DeclLoc, ArrayRef<Module *> Modules,
MissingImportKind MIK, bool Recover);
struct TypoExprState {
std::unique_ptr<TypoCorrectionConsumer> Consumer;
TypoDiagnosticGenerator DiagHandler;
TypoRecoveryCallback RecoveryHandler;
TypoExprState();
TypoExprState(TypoExprState &&other) noexcept;
TypoExprState &operator=(TypoExprState &&other) noexcept;
};
const TypoExprState &getTypoExprState(TypoExpr *TE) const;
/// Clears the state of the given TypoExpr.
void clearDelayedTypo(TypoExpr *TE);
/// Called on #pragma clang __debug dump II
void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
@ -9832,23 +9724,15 @@ private:
/// Determine if we could use all the declarations in the module.
bool isUsableModule(const Module *M);
/// Helper for CorrectTypo and CorrectTypoDelayed used to create and
/// populate a new TypoCorrectionConsumer. Returns nullptr if typo correction
/// should be skipped entirely.
/// Helper for CorrectTypo used to create and populate a new
/// TypoCorrectionConsumer. Returns nullptr if typo correction should be
/// skipped entirely.
std::unique_ptr<TypoCorrectionConsumer> makeTypoCorrectionConsumer(
const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind,
Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
DeclContext *MemberContext, bool EnteringContext,
const ObjCObjectPointerType *OPT, bool ErrorRecovery);
/// The set of unhandled TypoExprs and their associated state.
llvm::MapVector<TypoExpr *, TypoExprState> DelayedTypos;
/// Creates a new TypoExpr AST node.
TypoExpr *createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
TypoDiagnosticGenerator TDG,
TypoRecoveryCallback TRC, SourceLocation TypoLoc);
/// Cache for module units which is usable for current module.
llvm::DenseSet<const Module *> UsableModuleUnitsCache;

View File

@ -314,20 +314,6 @@ private:
bool SearchNamespaces;
};
inline Sema::TypoExprState::TypoExprState() {}
inline Sema::TypoExprState::TypoExprState(TypoExprState &&other) noexcept {
*this = std::move(other);
}
inline Sema::TypoExprState &Sema::TypoExprState::
operator=(Sema::TypoExprState &&other) noexcept {
Consumer = std::move(other.Consumer);
DiagHandler = std::move(other.DiagHandler);
RecoveryHandler = std::move(other.RecoveryHandler);
return *this;
}
} // end namespace clang
#endif

View File

@ -3611,7 +3611,6 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case PackExpansionExprClass:
case SubstNonTypeTemplateParmPackExprClass:
case FunctionParmPackExprClass:
case TypoExprClass:
case RecoveryExprClass:
case CXXFoldExprClass:
// Make a conservative assumption for dependent nodes.

View File

@ -129,7 +129,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
// FIXME: Is this wise? Should they get their own kind?
case Expr::UnresolvedLookupExprClass:
case Expr::UnresolvedMemberExprClass:
case Expr::TypoExprClass:
case Expr::DependentCoawaitExprClass:
case Expr::CXXDependentScopeMemberExprClass:
case Expr::DependentScopeDeclRefExprClass:

View File

@ -17327,7 +17327,6 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::CXXDeleteExprClass:
case Expr::CXXPseudoDestructorExprClass:
case Expr::UnresolvedLookupExprClass:
case Expr::TypoExprClass:
case Expr::RecoveryExprClass:
case Expr::DependentScopeDeclRefExprClass:
case Expr::CXXConstructExprClass:

View File

@ -4994,7 +4994,6 @@ recurse:
case Expr::ParenListExprClass:
case Expr::MSPropertyRefExprClass:
case Expr::MSPropertySubscriptExprClass:
case Expr::TypoExprClass: // This should no longer exist in the AST by now.
case Expr::RecoveryExprClass:
case Expr::ArraySectionExprClass:
case Expr::OMPArrayShapingExprClass:

View File

@ -2914,11 +2914,6 @@ void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
PrintExpr(Node->getSourceExpr());
}
void StmtPrinter::VisitTypoExpr(TypoExpr *Node) {
// TODO: Print something reasonable for a TypoExpr, if necessary.
llvm_unreachable("Cannot print TypoExpr nodes");
}
void StmtPrinter::VisitRecoveryExpr(RecoveryExpr *Node) {
OS << "<recovery-expr>(";
const char *Sep = "";

View File

@ -2361,10 +2361,6 @@ void StmtProfiler::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
VisitExpr(E);
}
void StmtProfiler::VisitTypoExpr(const TypoExpr *E) {
VisitExpr(E);
}
void StmtProfiler::VisitSourceLocExpr(const SourceLocExpr *E) {
VisitExpr(E);
}

View File

@ -422,7 +422,6 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
DefArgResult = ParseBraceInitializer();
} else
DefArgResult = ParseAssignmentExpression();
DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult, Param);
if (DefArgResult.isInvalid()) {
Actions.ActOnParamDefaultArgumentError(Param, EqualLoc,
/*DefaultArg=*/nullptr);

View File

@ -436,7 +436,6 @@ bool Parser::ParseAttributeArgumentList(
} else {
Expr = ParseAssignmentExpression();
}
Expr = Actions.CorrectDelayedTyposInExpr(Expr);
if (Tok.is(tok::ellipsis))
Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());
@ -472,15 +471,6 @@ bool Parser::ParseAttributeArgumentList(
Arg++;
}
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;
}
@ -565,9 +555,7 @@ unsigned Parser::ParseAttributeArgsCommon(
nullptr,
Sema::ExpressionEvaluationContextRecord::EK_AttrArgument);
ExprResult ArgExpr(
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
ExprResult ArgExpr = ParseAssignmentExpression();
if (ArgExpr.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
return 0;
@ -3212,9 +3200,7 @@ void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName,
Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, nullptr,
ExpressionKind::EK_AttrArgument);
ExprResult ArgExpr(
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
ExprResult ArgExpr = ParseAssignmentExpression();
if (ArgExpr.isInvalid()) {
Parens.skipToEnd();
return;
@ -6890,8 +6876,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// void (f()) requires true;
Diag(Tok, diag::err_requires_clause_inside_parens);
ConsumeToken();
ExprResult TrailingRequiresClause = Actions.CorrectDelayedTyposInExpr(
ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true));
ExprResult TrailingRequiresClause =
ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true);
if (TrailingRequiresClause.isUsable() && D.isFunctionDeclarator() &&
!D.hasTrailingRequiresClause())
// We're already ill-formed if we got here but we'll accept it anyway.
@ -7538,8 +7524,7 @@ void Parser::ParseParameterDeclarationClause(
Diag(Tok,
diag::err_requires_clause_on_declarator_not_declaring_a_function);
ConsumeToken();
Actions.CorrectDelayedTyposInExpr(
ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true));
ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true);
}
// Remember this parsed parameter in ParamInfo.
@ -7653,7 +7638,6 @@ void Parser::ParseParameterDeclarationClause(
}
DefArgResult = ParseAssignmentExpression();
}
DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult);
if (DefArgResult.isInvalid()) {
Actions.ActOnParamDefaultArgumentError(Param, EqualLoc,
/*DefaultArg=*/nullptr);
@ -7799,8 +7783,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
} else {
EnterExpressionEvaluationContext Unevaluated(
Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
NumElements =
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
NumElements = ParseAssignmentExpression();
}
} else {
if (StaticLoc.isValid()) {
@ -7937,8 +7920,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
bool isCastExpr;
ParsedType CastTy;
SourceRange CastRange;
ExprResult Operand = Actions.CorrectDelayedTyposInExpr(
ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, CastTy, CastRange));
ExprResult Operand =
ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, CastTy, CastRange);
if (HasParens)
DS.setTypeArgumentRange(CastRange);

View File

@ -1071,10 +1071,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
EnterExpressionEvaluationContext Unevaluated(
Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,
Sema::ExpressionEvaluationContextRecord::EK_Decltype);
Result = Actions.CorrectDelayedTyposInExpr(
ParseExpression(), /*InitDecl=*/nullptr,
/*RecoverUncorrectedTypos=*/false,
[](Expr *E) { return E->hasPlaceholderType() ? ExprError() : E; });
Result = ParseExpression();
if (Result.isInvalid()) {
DS.SetTypeSpecError();
if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) {
@ -4465,8 +4462,7 @@ bool Parser::ParseCXXAssumeAttributeArg(
Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
TentativeParsingAction TPA(*this);
ExprResult Res(
Actions.CorrectDelayedTyposInExpr(ParseConditionalExpression()));
ExprResult Res = ParseConditionalExpression();
if (Res.isInvalid()) {
TPA.Commit();
SkipUntil(tok::r_paren, tok::r_square, StopAtSemi | StopBeforeMatch);

View File

@ -183,7 +183,6 @@ ExprResult Parser::ParseConstraintExpression() {
ExprResult LHS(ParseCastExpression(CastParseKind::AnyCastExpr));
ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));
if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get())) {
Actions.CorrectDelayedTyposInExpr(Res);
return ExprError();
}
return Res;
@ -244,7 +243,6 @@ Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) {
// the rest of the addition expression). Try to parse the rest of it here.
if (PossibleNonPrimary)
E = RecoverFromNonPrimary(E, /*Note=*/!IsConstraintExpr);
Actions.CorrectDelayedTyposInExpr(E);
return ExprError();
}
return E;
@ -256,14 +254,11 @@ Parser::ParseConstraintLogicalAndExpression(bool IsTrailingRequiresClause) {
SourceLocation LogicalAndLoc = ConsumeToken();
ExprResult RHS = ParsePrimary();
if (RHS.isInvalid()) {
Actions.CorrectDelayedTyposInExpr(LHS);
return ExprError();
}
ExprResult Op = Actions.ActOnBinOp(getCurScope(), LogicalAndLoc,
tok::ampamp, LHS.get(), RHS.get());
if (!Op.isUsable()) {
Actions.CorrectDelayedTyposInExpr(RHS);
Actions.CorrectDelayedTyposInExpr(LHS);
return ExprError();
}
LHS = Op;
@ -281,14 +276,11 @@ Parser::ParseConstraintLogicalOrExpression(bool IsTrailingRequiresClause) {
ExprResult RHS =
ParseConstraintLogicalAndExpression(IsTrailingRequiresClause);
if (!RHS.isUsable()) {
Actions.CorrectDelayedTyposInExpr(LHS);
return ExprError();
}
ExprResult Op = Actions.ActOnBinOp(getCurScope(), LogicalOrLoc,
tok::pipepipe, LHS.get(), RHS.get());
if (!Op.isUsable()) {
Actions.CorrectDelayedTyposInExpr(RHS);
Actions.CorrectDelayedTyposInExpr(LHS);
return ExprError();
}
LHS = Op;
@ -408,7 +400,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
}
if (TernaryMiddle.isInvalid()) {
Actions.CorrectDelayedTyposInExpr(LHS);
LHS = ExprError();
TernaryMiddle = nullptr;
}
@ -466,11 +457,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
RHS = ParseCastExpression(CastParseKind::AnyCastExpr);
if (RHS.isInvalid()) {
// FIXME: Errors generated by the delayed typo correction should be
// printed before errors from parsing the RHS, not after.
Actions.CorrectDelayedTyposInExpr(LHS);
if (TernaryMiddle.isUsable())
TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle);
LHS = ExprError();
}
@ -503,11 +489,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
RHSIsInitList = false;
if (RHS.isInvalid()) {
// FIXME: Errors generated by the delayed typo correction should be
// printed before errors from ParseRHSOfBinaryExpression, not after.
Actions.CorrectDelayedTyposInExpr(LHS);
if (TernaryMiddle.isUsable())
TernaryMiddle = Actions.CorrectDelayedTyposInExpr(TernaryMiddle);
LHS = ExprError();
}
@ -571,17 +552,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
LHS = CondOp;
}
// In this case, ActOnBinOp or ActOnConditionalOp performed the
// CorrectDelayedTyposInExpr check.
if (!getLangOpts().CPlusPlus)
continue;
}
// Ensure potential typos aren't left undiagnosed.
if (LHS.isInvalid()) {
Actions.CorrectDelayedTyposInExpr(OrigLHS);
Actions.CorrectDelayedTyposInExpr(TernaryMiddle);
Actions.CorrectDelayedTyposInExpr(RHS);
}
}
}
@ -1711,7 +1681,6 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
// Reject array indices starting with a lambda-expression. '[[' is
// reserved for attributes.
if (CheckProhibitedCXX11Attribute()) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
return ExprError();
}
BalancedDelimiterTracker T(*this, tok::l_square);
@ -1737,8 +1706,6 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
} else {
Idx = ParseExpression(); // May be a comma expression
}
LHS = Actions.CorrectDelayedTyposInExpr(LHS);
Idx = Actions.CorrectDelayedTyposInExpr(Idx);
if (Idx.isInvalid()) {
HasError = true;
} else {
@ -1746,7 +1713,6 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
}
} else if (Tok.isNot(tok::r_square)) {
if (ParseExpressionList(ArgExprs)) {
LHS = Actions.CorrectDelayedTyposInExpr(LHS);
HasError = true;
}
}
@ -1762,7 +1728,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
// Consume ':'
ColonLocFirst = ConsumeToken();
if (Tok.isNot(tok::r_square))
Length = Actions.CorrectDelayedTyposInExpr(ParseExpression());
Length = ParseExpression();
}
} else if (ArgExprs.size() <= 1 && getLangOpts().OpenMP) {
ColonProtectionRAIIObject RAII(*this);
@ -1773,7 +1739,6 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
(getLangOpts().OpenMP < 50 ||
((Tok.isNot(tok::colon) && getLangOpts().OpenMP >= 50)))) {
Length = ParseExpression();
Length = Actions.CorrectDelayedTyposInExpr(Length);
}
}
if (getLangOpts().OpenMP >= 50 &&
@ -1789,8 +1754,6 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
}
SourceLocation RLoc = Tok.getLocation();
LHS = Actions.CorrectDelayedTyposInExpr(LHS);
if (!LHS.isInvalid() && !HasError && !Length.isInvalid() &&
!Stride.isInvalid() && Tok.is(tok::r_square)) {
if (ColonLocFirst.isValid() || ColonLocSecond.isValid()) {
@ -1838,7 +1801,6 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
SourceLocation OpenLoc = ConsumeToken();
if (ParseSimpleExpressionList(ExecConfigExprs)) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
LHS = ExprError();
}
@ -1889,16 +1851,12 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
PreferredType.enterFunctionArgument(Tok.getLocation(),
RunSignatureHelp);
}))) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
// If we got an error when parsing expression list, we don't call
// the CodeCompleteCall handler inside the parser. So call it here
// to make sure we get overload suggestions even when we are in the
// middle of a parameter.
if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
RunSignatureHelp();
} else if (LHS.isInvalid()) {
for (auto &E : ArgExprs)
Actions.CorrectDelayedTyposInExpr(E);
}
}
}
@ -1913,16 +1871,16 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
ArgExprs);
SkipUntil(tok::r_paren, StopAtSemi);
} else if (Tok.isNot(tok::r_paren)) {
bool HadDelayedTypo = false;
if (Actions.CorrectDelayedTyposInExpr(LHS).get() != LHS.get())
HadDelayedTypo = true;
bool HadErrors = false;
if (LHS.get()->containsErrors())
HadErrors = true;
for (auto &E : ArgExprs)
if (Actions.CorrectDelayedTyposInExpr(E).get() != E)
HadDelayedTypo = true;
// If there were delayed typos in the LHS or ArgExprs, call SkipUntil
// instead of PT.consumeClose() to avoid emitting extra diagnostics for
// the unmatched l_paren.
if (HadDelayedTypo)
if (E->containsErrors())
HadErrors = true;
// If there were errors in the LHS or ArgExprs, call SkipUntil instead
// of PT.consumeClose() to avoid emitting extra diagnostics for the
// unmatched l_paren.
if (HadErrors)
SkipUntil(tok::r_paren, StopAtSemi);
else
PT.consumeClose();
@ -2050,7 +2008,6 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
/*AllowConstructorName=*/
getLangOpts().MicrosoftExt && SS.isNotEmpty(),
/*AllowDeductionGuide=*/false, &TemplateKWLoc, Name)) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
LHS = ExprError();
}
@ -2921,8 +2878,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
do {
BalancedDelimiterTracker TS(*this, tok::l_square);
TS.consumeOpen();
ExprResult NumElements =
Actions.CorrectDelayedTyposInExpr(ParseExpression());
ExprResult NumElements = ParseExpression();
if (!NumElements.isUsable()) {
ErrorFound = true;
while (!SkipUntil(tok::r_square, tok::r_paren,
@ -2936,7 +2892,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// Match the ')'.
T.consumeClose();
RParenLoc = T.getCloseLocation();
Result = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
Result = ParseAssignmentExpression();
if (ErrorFound) {
Result = ExprError();
} else if (!Result.isInvalid()) {
@ -2948,12 +2904,6 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
InMessageExpressionRAIIObject InMessage(*this, false);
Result = ParseExpression(TypeCastState::MaybeTypeCast);
if (!getLangOpts().CPlusPlus && Result.isUsable()) {
// Correct typos in non-C++ code earlier so that implicit-cast-like
// expressions are parsed correctly.
Result = Actions.CorrectDelayedTyposInExpr(Result);
}
if (ExprType >= ParenParseOption::FoldExpr &&
isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) {
ExprType = ParenParseOption::FoldExpr;
@ -3057,8 +3007,7 @@ ExprResult Parser::ParseGenericSelectionExpression() {
// not evaluated."
EnterExpressionEvaluationContext Unevaluated(
Actions, Sema::ExpressionEvaluationContext::Unevaluated);
ControllingExpr =
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
ControllingExpr = ParseAssignmentExpression();
if (ControllingExpr.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
@ -3104,8 +3053,7 @@ ExprResult Parser::ParseGenericSelectionExpression() {
// FIXME: These expressions should be parsed in a potentially potentially
// evaluated context.
ExprResult ER(
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
ExprResult ER = ParseAssignmentExpression();
if (ER.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
@ -3199,8 +3147,7 @@ void Parser::injectEmbedTokens() {
bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
llvm::function_ref<void()> ExpressionStarts,
bool FailImmediatelyOnInvalidExpr,
bool EarlyTypoCorrection) {
bool FailImmediatelyOnInvalidExpr) {
bool SawError = false;
while (true) {
if (ExpressionStarts)
@ -3213,9 +3160,6 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
} else
Expr = ParseAssignmentExpression();
if (EarlyTypoCorrection)
Expr = Actions.CorrectDelayedTyposInExpr(Expr);
if (Tok.is(tok::ellipsis))
Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());
else if (Tok.is(tok::code_completion)) {
@ -3244,14 +3188,6 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
ConsumeToken();
checkPotentialAngleBracketDelimiter(Comma);
}
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;
}

View File

@ -972,8 +972,6 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
SourceLocation StartLoc = Tok.getLocation();
InMessageExpressionRAIIObject MaybeInMessageExpression(*this, true);
Init = ParseInitializer();
if (!Init.isInvalid())
Init = Actions.CorrectDelayedTyposInExpr(Init.get());
if (Tok.getLocation() != StartLoc) {
// Back out the lexing of the token after the initializer.
@ -1065,8 +1063,6 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
// enclosing the lambda-expression, rather than in the context of the
// lambda-expression itself.
ParsedType InitCaptureType;
if (Init.isUsable())
Init = Actions.CorrectDelayedTyposInExpr(Init.get());
if (Init.isUsable()) {
NonTentativeAction([&] {
// Get the pointer and store it in an lvalue, so we can use it as an
@ -3202,8 +3198,7 @@ ExprResult Parser::ParseRequiresExpression() {
// cv-qualifier-seq[opt] abstract-declarator[opt]
BalancedDelimiterTracker ExprBraces(*this, tok::l_brace);
ExprBraces.consumeOpen();
ExprResult Expression =
Actions.CorrectDelayedTyposInExpr(ParseExpression());
ExprResult Expression = ParseExpression();
if (!Expression.isUsable()) {
ExprBraces.skipToEnd();
SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch);
@ -3306,8 +3301,7 @@ ExprResult Parser::ParseRequiresExpression() {
// C++ [expr.prim.req.nested]
// nested-requirement:
// 'requires' constraint-expression ';'
ExprResult ConstraintExpr =
Actions.CorrectDelayedTyposInExpr(ParseConstraintExpression());
ExprResult ConstraintExpr = ParseConstraintExpression();
if (ConstraintExpr.isInvalid() || !ConstraintExpr.isUsable()) {
SkipUntil(tok::semi, tok::r_brace,
SkipUntilFlags::StopBeforeMatch);
@ -3373,8 +3367,7 @@ ExprResult Parser::ParseRequiresExpression() {
// simple-requirement:
// expression ';'
SourceLocation StartLoc = Tok.getLocation();
ExprResult Expression =
Actions.CorrectDelayedTyposInExpr(ParseExpression());
ExprResult Expression = ParseExpression();
if (!Expression.isUsable()) {
SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch);
break;

View File

@ -477,8 +477,6 @@ 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.isUsable()) {
InitExprs.push_back(SubElt.get());

View File

@ -2629,10 +2629,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
if (!Tok.isSimpleTypeSpecifier(getLangOpts())) {
// objc-receiver:
// expression
// Make sure any typos in the receiver are corrected or diagnosed, so that
// proper recovery can happen. FIXME: Perhaps filter the corrected expr to
// only the things that are valid ObjC receivers?
ExprResult Receiver = Actions.CorrectDelayedTyposInExpr(ParseExpression());
ExprResult Receiver = ParseExpression();
if (Receiver.isInvalid())
return true;
@ -2809,7 +2806,7 @@ ExprResult Parser::ParseObjCMessageExpression() {
}
// Otherwise, an arbitrary expression can be the receiver of a send.
ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression());
ExprResult Res = ParseExpression();
if (Res.isInvalid()) {
SkipUntil(tok::r_square, StopAtSemi);
return Res;
@ -2930,8 +2927,6 @@ 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) <<
@ -3078,10 +3073,6 @@ ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
return Res;
}
Res = Actions.CorrectDelayedTyposInExpr(Res.get());
if (Res.isInvalid())
HasInvalidEltExpr = true;
// Parse the ellipsis that indicates a pack expansion.
if (Tok.is(tok::ellipsis))
Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken());
@ -3108,7 +3099,6 @@ ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
SmallVector<ObjCDictionaryElement, 4> Elements; // dictionary elements.
ConsumeBrace(); // consume the l_square.
bool HasInvalidEltExpr = false;
while (Tok.isNot(tok::r_brace)) {
// Parse the comma separated key : value expressions.
ExprResult KeyExpr;
@ -3138,12 +3128,6 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
return ValueExpr;
}
// Check the key and value for possible typos
KeyExpr = Actions.CorrectDelayedTyposInExpr(KeyExpr.get());
ValueExpr = Actions.CorrectDelayedTyposInExpr(ValueExpr.get());
if (KeyExpr.isInvalid() || ValueExpr.isInvalid())
HasInvalidEltExpr = true;
// Parse the ellipsis that designates this as a pack expansion. Do not
// ActOnPackExpansion here, leave it to template instantiation time where
// we can get better diagnostics.
@ -3163,9 +3147,6 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
}
SourceLocation EndLoc = ConsumeBrace();
if (HasInvalidEltExpr)
return ExprError();
// Create the ObjCDictionaryLiteral.
return Actions.ObjC().BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc),
Elements);

View File

@ -653,7 +653,7 @@ ExprResult Parser::ParseOpenACCConditionExpr() {
// it does in an if/while/etc (See ParseCXXCondition), however as it was
// written with Fortran/C in mind, we're going to assume it just means an
// 'expression evaluating to boolean'.
ExprResult ER = getActions().CorrectDelayedTyposInExpr(ParseExpression());
ExprResult ER = ParseExpression();
if (!ER.isUsable())
return ER;
@ -761,12 +761,6 @@ Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
if (!ER.isUsable())
return {ER, OpenACCParseCanContinue::Cannot};
// Parsing can continue after the initial assignment expression parsing, so
// even if there was a typo, we can continue.
ER = getActions().CorrectDelayedTyposInExpr(ER);
if (!ER.isUsable())
return {ER, OpenACCParseCanContinue::Can};
return {getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get()),
OpenACCParseCanContinue::Can};
}
@ -836,8 +830,7 @@ ExprResult Parser::ParseOpenACCSizeExpr(OpenACCClauseKind CK) {
return getActions().OpenACC().ActOnOpenACCAsteriskSizeExpr(AsteriskLoc);
}
ExprResult SizeExpr =
getActions().CorrectDelayedTyposInExpr(ParseConstantExpression());
ExprResult SizeExpr = ParseConstantExpression();
if (!SizeExpr.isUsable())
return SizeExpr;
@ -891,8 +884,7 @@ Parser::OpenACCGangArgRes Parser::ParseOpenACCGangArg(SourceLocation GangLoc) {
ConsumeToken();
// Parse this as a const-expression, and we'll check its integer-ness/value
// in CheckGangExpr.
ExprResult Res =
getActions().CorrectDelayedTyposInExpr(ParseConstantExpression());
ExprResult Res = ParseConstantExpression();
return {OpenACCGangKind::Dim, Res};
}
@ -1089,8 +1081,7 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
case OpenACCClauseKind::Collapse: {
bool HasForce = tryParseAndConsumeSpecialTokenKind(
*this, OpenACCSpecialTokenKind::Force, ClauseKind);
ExprResult LoopCount =
getActions().CorrectDelayedTyposInExpr(ParseConstantExpression());
ExprResult LoopCount = ParseConstantExpression();
if (LoopCount.isInvalid()) {
Parens.skipToEnd();
return OpenACCCanContinue();
@ -1387,7 +1378,7 @@ ExprResult Parser::ParseOpenACCIDExpression() {
/*isAddressOfOperand=*/false);
}
return getActions().CorrectDelayedTyposInExpr(Res);
return Res;
}
std::variant<std::monostate, clang::StringLiteral *, IdentifierInfo *>
@ -1414,9 +1405,8 @@ Parser::ParseOpenACCBindClauseArgument() {
return std::monostate{};
}
ExprResult Res =
getActions().CorrectDelayedTyposInExpr(ParseStringLiteralExpression(
/*AllowUserDefinedLiteral=*/false, /*Unevaluated=*/true));
ExprResult Res = ParseStringLiteralExpression(
/*AllowUserDefinedLiteral=*/false, /*Unevaluated=*/true);
if (!Res.isUsable())
return std::monostate{};
return cast<StringLiteral>(Res.get());
@ -1430,10 +1420,6 @@ Parser::OpenACCVarParseResult Parser::ParseOpenACCVar(OpenACCDirectiveKind DK,
if (!Res.isUsable())
return {Res, OpenACCParseCanContinue::Cannot};
Res = getActions().CorrectDelayedTyposInExpr(Res.get());
if (!Res.isUsable())
return {Res, OpenACCParseCanContinue::Can};
Res = getActions().OpenACC().ActOnVar(DK, CK, Res.get());
return {Res, OpenACCParseCanContinue::Can};

View File

@ -3600,8 +3600,7 @@ bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
while (Tok.isNot(tok::r_paren)) {
SourceLocation Loc = Tok.getLocation();
ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr(
ParseRHSOfBinaryExpression(LHS, prec::Conditional));
ExprResult PTExpr = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
/*DiscardedValue=*/false);
if (PTExpr.isUsable()) {
@ -3662,8 +3661,7 @@ OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
// Parse the variable.
SourceLocation VarLoc = Tok.getLocation();
ExprResult InteropVarExpr =
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
ExprResult InteropVarExpr = ParseAssignmentExpression();
if (!InteropVarExpr.isUsable()) {
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
@ -4288,8 +4286,7 @@ ExprResult Parser::ParseOpenMPIteratorsExpr() {
// Parse <begin>
SourceLocation Loc = Tok.getLocation();
ExprResult LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
ExprResult Begin = Actions.CorrectDelayedTyposInExpr(
ParseRHSOfBinaryExpression(LHS, prec::Conditional));
ExprResult Begin = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
/*DiscardedValue=*/false);
// Parse ':'.
@ -4300,8 +4297,7 @@ ExprResult Parser::ParseOpenMPIteratorsExpr() {
// Parse <end>
Loc = Tok.getLocation();
LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
ExprResult End = Actions.CorrectDelayedTyposInExpr(
ParseRHSOfBinaryExpression(LHS, prec::Conditional));
ExprResult End = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
End = Actions.ActOnFinishFullExpr(End.get(), Loc,
/*DiscardedValue=*/false);
@ -4314,8 +4310,7 @@ ExprResult Parser::ParseOpenMPIteratorsExpr() {
// Parse <step>
Loc = Tok.getLocation();
LHS = ParseCastExpression(CastParseKind::AnyCastExpr);
Step = Actions.CorrectDelayedTyposInExpr(
ParseRHSOfBinaryExpression(LHS, prec::Conditional));
Step = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
/*DiscardedValue=*/false);
}
@ -4797,7 +4792,6 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
Tail = ParseOpenMPIteratorsExpr();
}
Tail = Actions.CorrectDelayedTyposInExpr(Tail);
Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
/*DiscardedValue=*/false);
if (Tail.isUsable() || Data.AllocateAlignment) {
@ -4858,8 +4852,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
if (!ParseOpenMPReservedLocator(Kind, Data, getLangOpts())) {
// Parse variable
ExprResult VarExpr =
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
ExprResult VarExpr = ParseAssignmentExpression();
if (VarExpr.isUsable()) {
Vars.push_back(VarExpr.get());
} else {
@ -4896,6 +4889,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
SourceLocation ELoc = ConsumeToken();
if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
bool Malformed = false;
while (Tok.isNot(tok::r_paren)) {
if (Tok.is(tok::identifier)) {
// identifier could be a linear kind (val, uval, ref) or step
@ -4932,6 +4926,11 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
ModifierFound = true;
} else {
StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
if (!StepFound) {
Malformed = true;
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
}
}
} else {
// parse an integer expression as step size
@ -4943,7 +4942,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
break;
}
if (!StepFound && !ModifierFound)
if (!Malformed && !StepFound && !ModifierFound)
Diag(ELoc, diag::err_expected_expression);
} else {
// for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)

View File

@ -602,7 +602,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
{
ParseScopeFlags FilterScope(this, getCurScope()->getFlags() |
Scope::SEHFilterScope);
FilterExpr = Actions.CorrectDelayedTyposInExpr(ParseExpression());
FilterExpr = ParseExpression();
}
if (getLangOpts().Borland) {
@ -1832,11 +1832,7 @@ StmtResult Parser::ParseDoStatement() {
SourceLocation Start = Tok.getLocation();
ExprResult Cond = ParseExpression();
// Correct the typos in condition before closing the scope.
if (Cond.isUsable())
Cond = Actions.CorrectDelayedTyposInExpr(Cond, /*InitDecl=*/nullptr,
/*RecoverUncorrectedTypos=*/true);
else {
if (!Cond.isUsable()) {
if (!Tok.isOneOf(tok::r_paren, tok::r_square, tok::r_brace))
SkipUntil(tok::semi);
Cond = Actions.CreateRecoveryExpr(
@ -2018,7 +2014,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
}
} else {
ProhibitAttributes(attrs);
Value = Actions.CorrectDelayedTyposInExpr(ParseExpression());
Value = ParseExpression();
ForEach = isTokIdentifier_in();
@ -2177,12 +2173,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
StmtResult ForEachStmt;
if (ForRangeInfo.ParsedForRangeDecl()) {
ExprResult CorrectedRange =
Actions.CorrectDelayedTyposInExpr(ForRangeInfo.RangeExpr.get());
ForRangeStmt = Actions.ActOnCXXForRangeStmt(
getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(),
ForRangeInfo.LoopVar.get(), ForRangeInfo.ColonLoc, CorrectedRange.get(),
T.getCloseLocation(), Sema::BFRK_Build,
ForRangeInfo.LoopVar.get(), ForRangeInfo.ColonLoc,
ForRangeInfo.RangeExpr.get(), T.getCloseLocation(), Sema::BFRK_Build,
ForRangeInfo.LifetimeExtendTemps);
} else if (ForEach) {
// Similarly, we need to do the semantic analysis for a for-range

View File

@ -864,7 +864,7 @@ bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
// Read the parenthesized expression.
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression());
ExprResult Res = ParseExpression();
T.consumeClose();
if (Res.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);

View File

@ -296,8 +296,7 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo,
return nullptr;
}
ExprResult ConstraintExprResult =
Actions.CorrectDelayedTyposInExpr(ParseConstraintExpression());
ExprResult ConstraintExprResult = ParseConstraintExpression();
if (ConstraintExprResult.isInvalid()) {
SkipUntil(tok::semi);
if (D)

View File

@ -1227,15 +1227,6 @@ void Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) {
assert(LateParsedInstantiations.empty() &&
"end of TU template instantiation should not create more "
"late-parsed templates");
// Report diagnostics for uncorrected delayed typos. Ideally all of them
// should have been corrected by that time, but it is very hard to cover all
// cases in practice.
for (const auto &Typo : DelayedTypos) {
// We pass an empty TypoCorrection to indicate no correction was performed.
Typo.second.DiagHandler(TypoCorrection());
}
DelayedTypos.clear();
}
void Sema::ActOnEndOfTranslationUnit() {

View File

@ -2648,8 +2648,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
bool IsDelete = BuiltinID == Builtin::BI__builtin_operator_delete;
ExprResult Res =
BuiltinOperatorNewDeleteOverloaded(TheCallResult, IsDelete);
if (Res.isInvalid())
CorrectDelayedTyposInExpr(TheCallResult.get());
return Res;
}
case Builtin::BI__builtin_dump_struct:

View File

@ -309,15 +309,6 @@ static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
if (Result.isInvalid())
return ExprError();
// We meant exactly what we asked for. No need for typo correction.
if (auto *TE = dyn_cast<TypoExpr>(Result.get())) {
S.clearDelayedTypo(TE);
S.Diag(Loc, diag::err_no_member)
<< NameInfo.getName() << Base->getType()->getAsCXXRecordDecl()
<< Base->getSourceRange();
return ExprError();
}
auto EndLoc = Args.empty() ? Loc : Args.back()->getEndLoc();
return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, EndLoc, nullptr);
}
@ -811,7 +802,6 @@ ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
return ExprError();
if (!ActOnCoroutineBodyStart(S, Loc, "co_await")) {
CorrectDelayedTyposInExpr(E);
return ExprError();
}
@ -970,7 +960,6 @@ ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
return ExprError();
if (!ActOnCoroutineBodyStart(S, Loc, "co_yield")) {
CorrectDelayedTyposInExpr(E);
return ExprError();
}
@ -1025,7 +1014,6 @@ ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) {
StmtResult Sema::ActOnCoreturnStmt(Scope *S, SourceLocation Loc, Expr *E) {
if (!ActOnCoroutineBodyStart(S, Loc, "co_return")) {
CorrectDelayedTyposInExpr(E);
return StmtError();
}
return BuildCoreturnStmt(Loc, E);

View File

@ -13584,7 +13584,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// If there is no declaration, there was an error parsing it. Just ignore
// the initializer.
if (!RealDecl) {
CorrectDelayedTyposInExpr(Init, dyn_cast_or_null<VarDecl>(RealDecl));
return;
}
@ -13607,12 +13606,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
}
if (VDecl->isInvalidDecl()) {
ExprResult Res = CorrectDelayedTyposInExpr(Init, VDecl);
SmallVector<Expr *> SubExprs;
if (Res.isUsable())
SubExprs.push_back(Res.get());
ExprResult Recovery =
CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), SubExprs);
CreateRecoveryExpr(Init->getBeginLoc(), Init->getEndLoc(), {Init});
if (Expr *E = Recovery.get())
VDecl->setInit(E);
return;
@ -13627,23 +13622,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
if (VDecl->getType()->isUndeducedType()) {
// Attempt typo correction early so that the type of the init expression can
// be deduced based on the chosen correction if the original init contains a
// TypoExpr.
ExprResult Res = CorrectDelayedTyposInExpr(Init, VDecl);
if (!Res.isUsable()) {
// There are unresolved typos in Init, just drop them.
// FIXME: improve the recovery strategy to preserve the Init.
RealDecl->setInvalidDecl();
return;
}
if (Res.get()->containsErrors()) {
if (Init->containsErrors()) {
// Invalidate the decl as we don't know the type for recovery-expr yet.
RealDecl->setInvalidDecl();
VDecl->setInit(Res.get());
VDecl->setInit(Init);
return;
}
Init = Res.get();
if (DeduceVariableDeclarationType(VDecl, DirectInit, Init))
return;
@ -13789,23 +13773,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
InitializedFromParenListExpr = true;
}
// Try to correct any TypoExprs in the initialization arguments.
for (size_t Idx = 0; Idx < Args.size(); ++Idx) {
ExprResult Res = CorrectDelayedTyposInExpr(
Args[Idx], VDecl, /*RecoverUncorrectedTypos=*/true,
[this, Entity, Kind](Expr *E) {
InitializationSequence Init(*this, Entity, Kind, MultiExprArg(E));
return Init.Failed() ? ExprError() : E;
});
if (!Res.isUsable()) {
VDecl->setInvalidDecl();
} else if (Res.get() != Args[Idx]) {
Args[Idx] = Res.get();
}
}
if (VDecl->isInvalidDecl())
return;
InitializationSequence InitSeq(*this, Entity, Kind, Args,
/*TopLevelOfInitList=*/false,
/*TreatUnavailableAsInvalid=*/false);

View File

@ -4154,10 +4154,6 @@ ExprResult Sema::ActOnRequiresClause(ExprResult ConstraintExpr) {
if (ConstraintExpr.isInvalid())
return ExprError();
ConstraintExpr = CorrectDelayedTyposInExpr(ConstraintExpr);
if (ConstraintExpr.isInvalid())
return ExprError();
if (DiagnoseUnexpandedParameterPack(ConstraintExpr.get(),
UPPC_RequiresClause))
return ExprError();
@ -4207,23 +4203,20 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
return;
}
ExprResult Init = CorrectDelayedTyposInExpr(InitExpr, /*InitDecl=*/nullptr,
/*RecoverUncorrectedTypos=*/true);
assert(Init.isUsable() && "Init should at least have a RecoveryExpr");
if (!FD->getType()->isDependentType() && !Init.get()->isTypeDependent()) {
Init = ConvertMemberDefaultInitExpression(FD, Init.get(), InitLoc);
if (!FD->getType()->isDependentType() && !InitExpr.get()->isTypeDependent()) {
InitExpr = ConvertMemberDefaultInitExpression(FD, InitExpr.get(), InitLoc);
// C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
if (!Init.isInvalid())
Init = ActOnFinishFullExpr(Init.get(), /*DiscarededValue=*/false);
if (Init.isInvalid()) {
if (!InitExpr.isInvalid())
InitExpr = ActOnFinishFullExpr(InitExpr.get(), /*DiscarededValue=*/false);
if (InitExpr.isInvalid()) {
FD->setInvalidDecl();
return;
}
}
FD->setInClassInitializer(Init.get());
FD->setInClassInitializer(InitExpr.get());
}
/// Find the direct and/or virtual base specifiers that
@ -4393,13 +4386,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
SourceLocation IdLoc,
Expr *Init,
SourceLocation EllipsisLoc) {
ExprResult Res = CorrectDelayedTyposInExpr(Init, /*InitDecl=*/nullptr,
/*RecoverUncorrectedTypos=*/true);
if (!Res.isUsable())
return true;
Init = Res.get();
if (!ConstructorD)
if (!ConstructorD || !Init)
return true;
AdjustDeclIfTemplate(ConstructorD);

View File

@ -1368,7 +1368,6 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
case Expr::UnaryExprOrTypeTraitExprClass:
case Expr::UnresolvedLookupExprClass:
case Expr::UnresolvedMemberExprClass:
case Expr::TypoExprClass:
// FIXME: Many of the above can throw.
return CT_Cannot;

View File

@ -2544,8 +2544,7 @@ bool Sema::DiagnoseDependentMemberLookup(const LookupResult &R) {
bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
CorrectionCandidateCallback &CCC,
TemplateArgumentListInfo *ExplicitTemplateArgs,
ArrayRef<Expr *> Args, DeclContext *LookupCtx,
TypoExpr **Out) {
ArrayRef<Expr *> Args, DeclContext *LookupCtx) {
DeclarationName Name = R.getLookupName();
SourceRange NameRange = R.getLookupNameInfo().getSourceRange();
@ -2604,21 +2603,9 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
// We didn't find anything, so try to correct for a typo.
TypoCorrection Corrected;
if (S && Out) {
assert(!ExplicitTemplateArgs &&
"Diagnosing an empty lookup with explicit template args!");
*Out = CorrectTypoDelayed(
R.getLookupNameInfo(), R.getLookupKind(), S, &SS, CCC,
[=](const TypoCorrection &TC) {
emitEmptyLookupTypoDiagnostic(TC, *this, SS, Name, NameRange,
diagnostic, diagnostic_suggest);
},
nullptr, CorrectTypoKind::ErrorRecovery, LookupCtx);
if (*Out)
return true;
} else if (S && (Corrected = CorrectTypo(
R.getLookupNameInfo(), R.getLookupKind(), S, &SS, CCC,
CorrectTypoKind::ErrorRecovery, LookupCtx))) {
if (S && (Corrected =
CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
CCC, CorrectTypoKind::ErrorRecovery, LookupCtx))) {
std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
bool DroppedSpecifier =
Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr;
@ -2880,7 +2867,6 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
// If this name wasn't predeclared and if this is not a function
// call, diagnose the problem.
TypoExpr *TE = nullptr;
DefaultFilterCCC DefaultValidator(II, SS.isValid() ? SS.getScopeRep()
: nullptr);
DefaultValidator.IsAddressOfOperand = IsAddressOfOperand;
@ -2896,29 +2882,8 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
// a template name, but we happen to have always already looked up the name
// before we get here if it must be a template name.
if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator, nullptr,
{}, nullptr, &TE)) {
if (TE && KeywordReplacement) {
auto &State = getTypoExprState(TE);
auto BestTC = State.Consumer->getNextCorrection();
if (BestTC.isKeyword()) {
auto *II = BestTC.getCorrectionAsIdentifierInfo();
if (State.DiagHandler)
State.DiagHandler(BestTC);
KeywordReplacement->startToken();
KeywordReplacement->setKind(II->getTokenID());
KeywordReplacement->setIdentifierInfo(II);
KeywordReplacement->setLocation(BestTC.getCorrectionRange().getBegin());
// Clean up the state associated with the TypoExpr, since it has
// now been diagnosed (without a call to CorrectDelayedTyposInExpr).
clearDelayedTypo(TE);
// Signal that a correction to a keyword was performed by returning a
// valid-but-null ExprResult.
return (Expr*)nullptr;
}
State.Consumer->resetCorrectionStream();
}
return TE ? TE : ExprError();
}
{}, nullptr))
return ExprError();
assert(!R.empty() &&
"DiagnoseEmptyLookup returned false but added no results");
@ -7009,40 +6974,6 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
CurFPFeatureOverrides(), NumParams, UsesADL);
}
if (!Context.isDependenceAllowed()) {
// Forget about the nulled arguments since typo correction
// do not handle them well.
TheCall->shrinkNumArgs(Args.size());
// C cannot always handle TypoExpr nodes in builtin calls and direct
// function calls as their argument checking don't necessarily handle
// dependent types properly, so make sure any TypoExprs have been
// dealt with.
ExprResult Result = CorrectDelayedTyposInExpr(TheCall);
if (!Result.isUsable()) return ExprError();
CallExpr *TheOldCall = TheCall;
TheCall = dyn_cast<CallExpr>(Result.get());
bool CorrectedTypos = TheCall != TheOldCall;
if (!TheCall) return Result;
Args = llvm::ArrayRef(TheCall->getArgs(), TheCall->getNumArgs());
// A new call expression node was created if some typos were corrected.
// However it may not have been constructed with enough storage. In this
// case, rebuild the node with enough storage. The waste of space is
// immaterial since this only happens when some typos were corrected.
if (CorrectedTypos && Args.size() < NumParams) {
if (Config)
TheCall = CUDAKernelCallExpr::Create(
Context, Fn, cast<CallExpr>(Config), Args, ResultTy, VK_PRValue,
RParenLoc, CurFPFeatureOverrides(), NumParams);
else
TheCall =
CallExpr::Create(Context, Fn, Args, ResultTy, VK_PRValue, RParenLoc,
CurFPFeatureOverrides(), NumParams, UsesADL);
}
// We can now handle the nulled arguments for the default arguments.
TheCall->setNumArgsUnsafe(std::max<unsigned>(Args.size(), NumParams));
}
// Bail out early if calling a builtin with custom type checking.
if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) {
ExprResult E = CheckBuiltinFunctionCall(FDecl, BuiltinID, TheCall);
@ -7933,12 +7864,6 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
if (getLangOpts().CPlusPlus) {
// Check that there are no default arguments (C++ only).
CheckExtraCXXDefaultArguments(D);
} else {
// Make sure any TypoExprs have been dealt with.
ExprResult Res = CorrectDelayedTyposInExpr(CastExpr);
if (!Res.isUsable())
return ExprError();
CastExpr = Res.get();
}
checkUnusedDeclAttributes(D);
@ -8984,30 +8909,6 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
SourceLocation ColonLoc,
Expr *CondExpr, Expr *LHSExpr,
Expr *RHSExpr) {
if (!Context.isDependenceAllowed()) {
// C cannot handle TypoExpr nodes in the condition because it
// doesn't handle dependent types properly, so make sure any TypoExprs have
// been dealt with before checking the operands.
ExprResult CondResult = CorrectDelayedTyposInExpr(CondExpr);
ExprResult LHSResult = CorrectDelayedTyposInExpr(LHSExpr);
ExprResult RHSResult = CorrectDelayedTyposInExpr(RHSExpr);
if (!CondResult.isUsable())
return ExprError();
if (LHSExpr) {
if (!LHSResult.isUsable())
return ExprError();
}
if (!RHSResult.isUsable())
return ExprError();
CondExpr = CondResult.get();
LHSExpr = LHSResult.get();
RHSExpr = RHSResult.get();
}
// If this is the gnu "x ?: y" extension, analyze the types as though the LHS
// was the condition.
OpaqueValueExpr *opaqueValue = nullptr;
@ -15068,28 +14969,6 @@ static ExprResult convertHalfVecBinOp(Sema &S, ExprResult LHS, ExprResult RHS,
return convertVector(BO, ResultTy->castAs<VectorType>()->getElementType(), S);
}
static std::pair<ExprResult, ExprResult>
CorrectDelayedTyposInBinOp(Sema &S, BinaryOperatorKind Opc, Expr *LHSExpr,
Expr *RHSExpr) {
ExprResult LHS = LHSExpr, RHS = RHSExpr;
if (!S.Context.isDependenceAllowed()) {
// 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 = S.CorrectDelayedTyposInExpr(LHS);
RHS = S.CorrectDelayedTyposInExpr(
RHS, /*InitDecl=*/nullptr, /*RecoverUncorrectedTypos=*/false,
[Opc, LHS](Expr *E) {
if (Opc != BO_Assign)
return ExprResult(E);
// Avoid correcting the RHS to the same Expr as the LHS.
Decl *D = getDeclFromExpr(E);
return (D && D == getDeclFromExpr(LHS.get())) ? ExprError() : E;
});
}
return std::make_pair(LHS, RHS);
}
/// Returns true if conversion between vectors of halfs and vectors of floats
/// is needed.
static bool needsConversionOfHalfVec(bool OpRequiresConversion, ASTContext &Ctx,
@ -15146,7 +15025,6 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
ExprObjectKind OK = OK_Ordinary;
bool ConvertHalfVec = false;
std::tie(LHS, RHS) = CorrectDelayedTyposInBinOp(*this, Opc, LHSExpr, RHSExpr);
if (!LHS.isUsable() || !RHS.isUsable())
return ExprError();
@ -15662,12 +15540,8 @@ static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
BinaryOperatorKind Opc, Expr *LHSExpr,
Expr *RHSExpr, bool ForFoldExpression) {
ExprResult LHS, RHS;
std::tie(LHS, RHS) = CorrectDelayedTyposInBinOp(*this, Opc, LHSExpr, RHSExpr);
if (!LHS.isUsable() || !RHS.isUsable())
if (!LHSExpr || !RHSExpr)
return ExprError();
LHSExpr = LHS.get();
RHSExpr = RHS.get();
// We want to end up calling one of SemaPseudoObject::checkAssignment
// (if the LHS is a pseudo-object), BuildOverloadedBinOp (if
@ -18194,8 +18068,6 @@ HandleImmediateInvocations(Sema &SemaRef,
void Sema::PopExpressionEvaluationContext() {
ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
unsigned NumTypos = Rec.NumTypos;
if (!Rec.Lambdas.empty()) {
using ExpressionKind = ExpressionEvaluationContextRecord::ExpressionKind;
if (!getLangOpts().CPlusPlus20 &&
@ -18263,9 +18135,6 @@ void Sema::PopExpressionEvaluationContext() {
// Pop the current expression evaluation context off the stack.
ExprEvalContexts.pop_back();
// The global expression evaluation context record is never popped.
ExprEvalContexts.back().NumTypos += NumTypos;
}
void Sema::DiscardCleanupsInEvaluationContext() {
@ -20023,8 +19892,6 @@ ExprResult Sema::CheckLValueToRValueConversionOperand(Expr *E) {
}
ExprResult Sema::ActOnConstantExpression(ExprResult Res) {
Res = CorrectDelayedTyposInExpr(Res);
if (!Res.isUsable())
return Res;
@ -21350,15 +21217,6 @@ static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) {
}
ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
if (!Context.isDependenceAllowed()) {
// 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;

View File

@ -1500,13 +1500,7 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
auto Result = BuildCXXTypeConstructExpr(TInfo, LParenOrBraceLoc, exprs,
RParenOrBraceLoc, ListInitialization);
// Avoid creating a non-type-dependent expression that contains typos.
// Non-type-dependent expressions are liable to be discarded without
// checking for embedded typos.
if (!Result.isInvalid() && Result.get()->isInstantiationDependent() &&
!Result.get()->isTypeDependent())
Result = CorrectDelayedTyposInExpr(Result.get());
else if (Result.isInvalid())
if (Result.isInvalid())
Result = CreateRecoveryExpr(TInfo->getTypeLoc().getBeginLoc(),
RParenOrBraceLoc, exprs, Ty);
return Result;
@ -7698,372 +7692,6 @@ static ExprResult attemptRecovery(Sema &SemaRef,
/*AcceptInvalidDecl*/ true);
}
namespace {
class FindTypoExprs : public DynamicRecursiveASTVisitor {
llvm::SmallSetVector<TypoExpr *, 2> &TypoExprs;
public:
explicit FindTypoExprs(llvm::SmallSetVector<TypoExpr *, 2> &TypoExprs)
: TypoExprs(TypoExprs) {}
bool VisitTypoExpr(TypoExpr *TE) override {
TypoExprs.insert(TE);
return true;
}
};
class TransformTypos : public TreeTransform<TransformTypos> {
typedef TreeTransform<TransformTypos> BaseTransform;
VarDecl *InitDecl; // A decl to avoid as a correction because it is in the
// process of being initialized.
llvm::function_ref<ExprResult(Expr *)> ExprFilter;
llvm::SmallSetVector<TypoExpr *, 2> TypoExprs, AmbiguousTypoExprs;
llvm::SmallDenseMap<TypoExpr *, ExprResult, 2> TransformCache;
llvm::SmallDenseMap<OverloadExpr *, Expr *, 4> OverloadResolution;
/// Emit diagnostics for all of the TypoExprs encountered.
///
/// If the TypoExprs were successfully corrected, then the diagnostics should
/// suggest the corrections. Otherwise the diagnostics will not suggest
/// anything (having been passed an empty TypoCorrection).
///
/// If we've failed to correct due to ambiguous corrections, we need to
/// be sure to pass empty corrections and replacements. Otherwise it's
/// possible that the Consumer has a TypoCorrection that failed to ambiguity
/// and we don't want to report those diagnostics.
void EmitAllDiagnostics(bool IsAmbiguous) {
for (TypoExpr *TE : TypoExprs) {
auto &State = SemaRef.getTypoExprState(TE);
if (State.DiagHandler) {
TypoCorrection TC = IsAmbiguous
? TypoCorrection() : State.Consumer->getCurrentCorrection();
ExprResult Replacement = IsAmbiguous ? ExprError() : TransformCache[TE];
// Extract the NamedDecl from the transformed TypoExpr and add it to the
// TypoCorrection, replacing the existing decls. This ensures the right
// NamedDecl is used in diagnostics e.g. in the case where overload
// resolution was used to select one from several possible decls that
// had been stored in the TypoCorrection.
if (auto *ND = getDeclFromExpr(
Replacement.isInvalid() ? nullptr : Replacement.get()))
TC.setCorrectionDecl(ND);
State.DiagHandler(TC);
}
SemaRef.clearDelayedTypo(TE);
}
}
/// Try to advance the typo correction state of the first unfinished TypoExpr.
/// We allow advancement of the correction stream by removing it from the
/// TransformCache which allows `TransformTypoExpr` to advance during the
/// next transformation attempt.
///
/// Any substitution attempts for the previous TypoExprs (which must have been
/// finished) will need to be retried since it's possible that they will now
/// be invalid given the latest advancement.
///
/// We need to be sure that we're making progress - it's possible that the
/// tree is so malformed that the transform never makes it to the
/// `TransformTypoExpr`.
///
/// Returns true if there are any untried correction combinations.
bool CheckAndAdvanceTypoExprCorrectionStreams() {
for (auto *TE : TypoExprs) {
auto &State = SemaRef.getTypoExprState(TE);
TransformCache.erase(TE);
if (!State.Consumer->hasMadeAnyCorrectionProgress())
return false;
if (!State.Consumer->finished())
return true;
State.Consumer->resetCorrectionStream();
}
return false;
}
NamedDecl *getDeclFromExpr(Expr *E) {
if (auto *OE = dyn_cast_or_null<OverloadExpr>(E))
E = OverloadResolution[OE];
if (!E)
return nullptr;
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
return DRE->getFoundDecl();
if (auto *ME = dyn_cast<MemberExpr>(E))
return ME->getFoundDecl();
// FIXME: Add any other expr types that could be seen by the delayed typo
// correction TreeTransform for which the corresponding TypoCorrection could
// contain multiple decls.
return nullptr;
}
ExprResult TryTransform(Expr *E) {
Sema::SFINAETrap Trap(SemaRef);
ExprResult Res = TransformExpr(E);
if (Trap.hasErrorOccurred() || Res.isInvalid())
return ExprError();
return ExprFilter(Res.get());
}
// Since correcting typos may intoduce new TypoExprs, this function
// checks for new TypoExprs and recurses if it finds any. Note that it will
// only succeed if it is able to correct all typos in the given expression.
ExprResult CheckForRecursiveTypos(ExprResult Res, bool &IsAmbiguous) {
if (Res.isInvalid()) {
return Res;
}
// Check to see if any new TypoExprs were created. If so, we need to recurse
// to check their validity.
Expr *FixedExpr = Res.get();
auto SavedTypoExprs = std::move(TypoExprs);
auto SavedAmbiguousTypoExprs = std::move(AmbiguousTypoExprs);
TypoExprs.clear();
AmbiguousTypoExprs.clear();
FindTypoExprs(TypoExprs).TraverseStmt(FixedExpr);
if (!TypoExprs.empty()) {
// Recurse to handle newly created TypoExprs. If we're not able to
// handle them, discard these TypoExprs.
ExprResult RecurResult =
RecursiveTransformLoop(FixedExpr, IsAmbiguous);
if (RecurResult.isInvalid()) {
Res = ExprError();
// Recursive corrections didn't work, wipe them away and don't add
// them to the TypoExprs set. Remove them from Sema's TypoExpr list
// since we don't want to clear them twice. Note: it's possible the
// TypoExprs were created recursively and thus won't be in our
// Sema's TypoExprs - they were created in our `RecursiveTransformLoop`.
auto &SemaTypoExprs = SemaRef.TypoExprs;
for (auto *TE : TypoExprs) {
TransformCache.erase(TE);
SemaRef.clearDelayedTypo(TE);
auto SI = find(SemaTypoExprs, TE);
if (SI != SemaTypoExprs.end()) {
SemaTypoExprs.erase(SI);
}
}
} else {
// TypoExpr is valid: add newly created TypoExprs since we were
// able to correct them.
Res = RecurResult;
SavedTypoExprs.set_union(TypoExprs);
}
}
TypoExprs = std::move(SavedTypoExprs);
AmbiguousTypoExprs = std::move(SavedAmbiguousTypoExprs);
return Res;
}
// Try to transform the given expression, looping through the correction
// candidates with `CheckAndAdvanceTypoExprCorrectionStreams`.
//
// If valid ambiguous typo corrections are seen, `IsAmbiguous` is set to
// true and this method immediately will return an `ExprError`.
ExprResult RecursiveTransformLoop(Expr *E, bool &IsAmbiguous) {
ExprResult Res;
auto SavedTypoExprs = std::move(SemaRef.TypoExprs);
SemaRef.TypoExprs.clear();
while (true) {
Res = CheckForRecursiveTypos(TryTransform(E), IsAmbiguous);
// Recursion encountered an ambiguous correction. This means that our
// correction itself is ambiguous, so stop now.
if (IsAmbiguous)
break;
// If the transform is still valid after checking for any new typos,
// it's good to go.
if (!Res.isInvalid())
break;
// The transform was invalid, see if we have any TypoExprs with untried
// correction candidates.
if (!CheckAndAdvanceTypoExprCorrectionStreams())
break;
}
// If we found a valid result, double check to make sure it's not ambiguous.
if (!IsAmbiguous && !Res.isInvalid() && !AmbiguousTypoExprs.empty()) {
auto SavedTransformCache =
llvm::SmallDenseMap<TypoExpr *, ExprResult, 2>(TransformCache);
// Ensure none of the TypoExprs have multiple typo correction candidates
// with the same edit length that pass all the checks and filters.
while (!AmbiguousTypoExprs.empty()) {
auto TE = AmbiguousTypoExprs.back();
// TryTransform itself can create new Typos, adding them to the TypoExpr map
// and invalidating our TypoExprState, so always fetch it instead of storing.
SemaRef.getTypoExprState(TE).Consumer->saveCurrentPosition();
TypoCorrection TC = SemaRef.getTypoExprState(TE).Consumer->peekNextCorrection();
TypoCorrection Next;
do {
// Fetch the next correction by erasing the typo from the cache and calling
// `TryTransform` which will iterate through corrections in
// `TransformTypoExpr`.
TransformCache.erase(TE);
ExprResult AmbigRes = CheckForRecursiveTypos(TryTransform(E), IsAmbiguous);
if (!AmbigRes.isInvalid() || IsAmbiguous) {
SemaRef.getTypoExprState(TE).Consumer->resetCorrectionStream();
SavedTransformCache.erase(TE);
Res = ExprError();
IsAmbiguous = true;
break;
}
} while ((Next = SemaRef.getTypoExprState(TE).Consumer->peekNextCorrection()) &&
Next.getEditDistance(false) == TC.getEditDistance(false));
if (IsAmbiguous)
break;
AmbiguousTypoExprs.remove(TE);
SemaRef.getTypoExprState(TE).Consumer->restoreSavedPosition();
TransformCache[TE] = SavedTransformCache[TE];
}
TransformCache = std::move(SavedTransformCache);
}
// Wipe away any newly created TypoExprs that we don't know about. Since we
// clear any invalid TypoExprs in `CheckForRecursiveTypos`, this is only
// possible if a `TypoExpr` is created during a transformation but then
// fails before we can discover it.
auto &SemaTypoExprs = SemaRef.TypoExprs;
for (auto Iterator = SemaTypoExprs.begin(); Iterator != SemaTypoExprs.end();) {
auto TE = *Iterator;
auto FI = find(TypoExprs, TE);
if (FI != TypoExprs.end()) {
Iterator++;
continue;
}
SemaRef.clearDelayedTypo(TE);
Iterator = SemaTypoExprs.erase(Iterator);
}
SemaRef.TypoExprs = std::move(SavedTypoExprs);
return Res;
}
public:
TransformTypos(Sema &SemaRef, VarDecl *InitDecl, llvm::function_ref<ExprResult(Expr *)> Filter)
: BaseTransform(SemaRef), InitDecl(InitDecl), ExprFilter(Filter) {}
ExprResult RebuildCallExpr(Expr *Callee, SourceLocation LParenLoc,
MultiExprArg Args,
SourceLocation RParenLoc,
Expr *ExecConfig = nullptr) {
auto Result = BaseTransform::RebuildCallExpr(Callee, LParenLoc, Args,
RParenLoc, ExecConfig);
if (auto *OE = dyn_cast<OverloadExpr>(Callee)) {
if (Result.isUsable()) {
Expr *ResultCall = Result.get();
if (auto *BE = dyn_cast<CXXBindTemporaryExpr>(ResultCall))
ResultCall = BE->getSubExpr();
if (auto *CE = dyn_cast<CallExpr>(ResultCall))
OverloadResolution[OE] = CE->getCallee();
}
}
return Result;
}
ExprResult TransformLambdaExpr(LambdaExpr *E) { return Owned(E); }
ExprResult TransformBlockExpr(BlockExpr *E) { return Owned(E); }
ExprResult Transform(Expr *E) {
bool IsAmbiguous = false;
ExprResult Res = RecursiveTransformLoop(E, IsAmbiguous);
if (!Res.isUsable())
FindTypoExprs(TypoExprs).TraverseStmt(E);
EmitAllDiagnostics(IsAmbiguous);
return Res;
}
ExprResult TransformTypoExpr(TypoExpr *E) {
// If the TypoExpr hasn't been seen before, record it. Otherwise, return the
// cached transformation result if there is one and the TypoExpr isn't the
// first one that was encountered.
auto &CacheEntry = TransformCache[E];
if (!TypoExprs.insert(E) && !CacheEntry.isUnset()) {
return CacheEntry;
}
auto &State = SemaRef.getTypoExprState(E);
assert(State.Consumer && "Cannot transform a cleared TypoExpr");
// For the first TypoExpr and an uncached TypoExpr, find the next likely
// typo correction and return it.
while (TypoCorrection TC = State.Consumer->getNextCorrection()) {
if (InitDecl && TC.getFoundDecl() == InitDecl)
continue;
// FIXME: If we would typo-correct to an invalid declaration, it's
// probably best to just suppress all errors from this typo correction.
ExprResult NE = State.RecoveryHandler ?
State.RecoveryHandler(SemaRef, E, TC) :
attemptRecovery(SemaRef, *State.Consumer, TC);
if (!NE.isInvalid()) {
// Check whether there may be a second viable correction with the same
// edit distance; if so, remember this TypoExpr may have an ambiguous
// correction so it can be more thoroughly vetted later.
TypoCorrection Next;
if ((Next = State.Consumer->peekNextCorrection()) &&
Next.getEditDistance(false) == TC.getEditDistance(false)) {
AmbiguousTypoExprs.insert(E);
} else {
AmbiguousTypoExprs.remove(E);
}
assert(!NE.isUnset() &&
"Typo was transformed into a valid-but-null ExprResult");
return CacheEntry = NE;
}
}
return CacheEntry = ExprError();
}
};
}
ExprResult
Sema::CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl,
bool RecoverUncorrectedTypos,
llvm::function_ref<ExprResult(Expr *)> Filter) {
// If the current evaluation context indicates there are uncorrected typos
// and the current expression isn't guaranteed to not have typos, try to
// resolve any TypoExpr nodes that might be in the expression.
if (E && !ExprEvalContexts.empty() && ExprEvalContexts.back().NumTypos &&
(E->isTypeDependent() || E->isValueDependent() ||
E->isInstantiationDependent())) {
auto TyposResolved = DelayedTypos.size();
auto Result = TransformTypos(*this, InitDecl, Filter).Transform(E);
TyposResolved -= DelayedTypos.size();
if (Result.isInvalid() || Result.get() != E) {
ExprEvalContexts.back().NumTypos -= TyposResolved;
if (Result.isInvalid() && RecoverUncorrectedTypos) {
struct TyposReplace : TreeTransform<TyposReplace> {
TyposReplace(Sema &SemaRef) : TreeTransform(SemaRef) {}
ExprResult TransformTypoExpr(clang::TypoExpr *E) {
return this->SemaRef.CreateRecoveryExpr(E->getBeginLoc(),
E->getEndLoc(), {});
}
} TT(*this);
return TT.TransformExpr(E);
}
return Result;
}
assert(TyposResolved == 0 && "Corrected typo but got same Expr back?");
}
return E;
}
ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
bool DiscardedValue, bool IsConstexpr,
bool IsTemplateArgument) {
@ -8095,8 +7723,6 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
DiagnoseUnusedExprResult(FullExpr.get(), diag::warn_unused_expr);
}
FullExpr = CorrectDelayedTyposInExpr(FullExpr.get(), /*InitDecl=*/nullptr,
/*RecoverUncorrectedTypos=*/true);
if (FullExpr.isInvalid())
return ExprError();

View File

@ -650,64 +650,11 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
return true;
}
namespace {
// Callback to only accept typo corrections that are either a ValueDecl or a
// FunctionTemplateDecl and are declared in the current record or, for a C++
// classes, one of its base classes.
class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback {
public:
explicit RecordMemberExprValidatorCCC(QualType RTy)
: Record(RTy->getAsRecordDecl()) {
// Don't add bare keywords to the consumer since they will always fail
// validation by virtue of not being associated with any decls.
WantTypeSpecifiers = false;
WantExpressionKeywords = false;
WantCXXNamedCasts = false;
WantFunctionLikeCasts = false;
WantRemainingKeywords = false;
}
bool ValidateCandidate(const TypoCorrection &candidate) override {
NamedDecl *ND = candidate.getCorrectionDecl();
// Don't accept candidates that cannot be member functions, constants,
// variables, or templates.
if (!ND || !(isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)))
return false;
// Accept candidates that occur in the current record.
if (Record->containsDecl(ND))
return true;
if (const auto *RD = dyn_cast<CXXRecordDecl>(Record)) {
// Accept candidates that occur in any of the current class' base classes.
for (const auto &BS : RD->bases()) {
if (const auto *BSTy = BS.getType()->getAs<RecordType>()) {
if (BSTy->getDecl()->containsDecl(ND))
return true;
}
}
}
return false;
}
std::unique_ptr<CorrectionCandidateCallback> clone() override {
return std::make_unique<RecordMemberExprValidatorCCC>(*this);
}
private:
const RecordDecl *const Record;
};
}
static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
Expr *BaseExpr, QualType RTy,
SourceLocation OpLoc, bool IsArrow,
CXXScopeSpec &SS, bool HasTemplateArgs,
SourceLocation TemplateKWLoc,
TypoExpr *&TE) {
SourceLocation TemplateKWLoc) {
SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange();
if (!RTy->isDependentType() &&
!SemaRef.isThisOutsideMemberFunctionBody(RTy) &&
@ -724,56 +671,6 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
/*EnteringContext=*/false, TemplateKWLoc);
SemaRef.LookupParsedName(R, /*S=*/nullptr, &SS, ObjectType);
if (!R.empty() || R.wasNotFoundInCurrentInstantiation())
return false;
DeclarationName Typo = R.getLookupName();
SourceLocation TypoLoc = R.getNameLoc();
// Recompute the lookup context.
DeclContext *DC = SS.isSet() ? SemaRef.computeDeclContext(SS)
: SemaRef.computeDeclContext(RTy);
struct QueryState {
Sema &SemaRef;
DeclarationNameInfo NameInfo;
Sema::LookupNameKind LookupKind;
RedeclarationKind Redecl;
};
QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(),
R.redeclarationKind()};
RecordMemberExprValidatorCCC CCC(RTy);
TE = SemaRef.CorrectTypoDelayed(
R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS, CCC,
[=, &SemaRef](const TypoCorrection &TC) {
if (TC) {
assert(!TC.isKeyword() &&
"Got a keyword as a correction for a member!");
bool DroppedSpecifier =
TC.WillReplaceSpecifier() &&
Typo.getAsString() == TC.getAsString(SemaRef.getLangOpts());
SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest)
<< Typo << DC << DroppedSpecifier
<< SS.getRange());
} else {
SemaRef.Diag(TypoLoc, diag::err_no_member)
<< Typo << DC << (SS.isSet() ? SS.getRange() : BaseRange);
}
},
[=](Sema &SemaRef, TypoExpr *TE, TypoCorrection TC) mutable {
LookupResult R(Q.SemaRef, Q.NameInfo, Q.LookupKind, Q.Redecl);
R.clear(); // Ensure there's no decls lingering in the shared state.
R.suppressDiagnostics();
R.setLookupName(TC.getCorrection());
for (NamedDecl *ND : TC)
R.addDecl(ND);
R.resolveKind();
return SemaRef.BuildMemberReferenceExpr(
BaseExpr, BaseExpr->getType(), OpLoc, IsArrow, SS, SourceLocation(),
nullptr, R, nullptr, nullptr);
},
CorrectTypoKind::ErrorRecovery, DC);
return false;
}
@ -793,15 +690,11 @@ ExprResult Sema::BuildMemberReferenceExpr(
// Implicit member accesses.
if (!Base) {
TypoExpr *TE = nullptr;
QualType RecordTy = BaseType;
if (IsArrow) RecordTy = RecordTy->castAs<PointerType>()->getPointeeType();
if (LookupMemberExprInRecord(*this, R, nullptr, RecordTy, OpLoc, IsArrow,
SS, TemplateArgs != nullptr, TemplateKWLoc,
TE))
SS, TemplateArgs != nullptr, TemplateKWLoc))
return ExprError();
if (TE)
return TE;
// Explicit member accesses.
} else {
@ -1396,16 +1289,15 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
// Handle field access to simple records.
if (BaseType->getAsRecordDecl()) {
TypoExpr *TE = nullptr;
if (LookupMemberExprInRecord(S, R, BaseExpr.get(), BaseType, OpLoc, IsArrow,
SS, HasTemplateArgs, TemplateKWLoc, TE))
SS, HasTemplateArgs, TemplateKWLoc))
return ExprError();
// Returning valid-but-null is how we indicate to the caller that
// the lookup result was filled in. If typo correction was attempted and
// failed, the lookup result will have been cleared--that combined with the
// valid-but-null ExprResult will trigger the appropriate diagnostics.
return ExprResult(TE);
return ExprResult{};
} else if (BaseType->isDependentType()) {
R.setNotFoundInCurrentInstantiation();
return ExprEmpty();

View File

@ -5444,40 +5444,6 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure && !SecondBestTC);
}
TypoExpr *Sema::CorrectTypoDelayed(
const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind,
Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, CorrectTypoKind Mode,
DeclContext *MemberContext, bool EnteringContext,
const ObjCObjectPointerType *OPT) {
auto Consumer = makeTypoCorrectionConsumer(
TypoName, LookupKind, S, SS, CCC, MemberContext, EnteringContext, OPT,
Mode == CorrectTypoKind::ErrorRecovery);
// Give the external sema source a chance to correct the typo.
TypoCorrection ExternalTypo;
if (ExternalSource && Consumer) {
ExternalTypo = ExternalSource->CorrectTypo(
TypoName, LookupKind, S, SS, *Consumer->getCorrectionValidator(),
MemberContext, EnteringContext, OPT);
if (ExternalTypo)
Consumer->addCorrection(ExternalTypo);
}
if (!Consumer || Consumer->empty())
return nullptr;
// Make sure the best edit distance (prior to adding any namespace qualifiers)
// is not more that about a third of the length of the typo's identifier.
unsigned ED = Consumer->getBestEditDistance(true);
IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo();
if (!ExternalTypo && ED > 0 && Typo->getName().size() / ED < 3)
return nullptr;
ExprEvalContexts.back().NumTypos++;
return createDelayedTypo(std::move(Consumer), std::move(TDG), std::move(TRC),
TypoName.getLoc());
}
void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) {
if (!CDecl) return;
@ -5802,32 +5768,6 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,
Diag(Correction.getCorrectionRange().getBegin(), PD);
}
TypoExpr *Sema::createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
TypoDiagnosticGenerator TDG,
TypoRecoveryCallback TRC,
SourceLocation TypoLoc) {
assert(TCC && "createDelayedTypo requires a valid TypoCorrectionConsumer");
auto TE = new (Context) TypoExpr(Context.DependentTy, TypoLoc);
auto &State = DelayedTypos[TE];
State.Consumer = std::move(TCC);
State.DiagHandler = std::move(TDG);
State.RecoveryHandler = std::move(TRC);
if (TE)
TypoExprs.push_back(TE);
return TE;
}
const Sema::TypoExprState &Sema::getTypoExprState(TypoExpr *TE) const {
auto Entry = DelayedTypos.find(TE);
assert(Entry != DelayedTypos.end() &&
"Failed to get the state for a TypoExpr!");
return Entry->second;
}
void Sema::clearDelayedTypo(TypoExpr *TE) {
DelayedTypos.erase(TE);
}
void Sema::ActOnPragmaDump(Scope *S, SourceLocation IILoc, IdentifierInfo *II) {
DeclarationNameInfo Name(II, IILoc);
LookupResult R(*this, Name, LookupAnyName,

View File

@ -124,17 +124,12 @@ ExprResult SemaObjC::CheckObjCForCollectionOperand(SourceLocation forLoc,
if (!collection)
return ExprError();
ExprResult result = SemaRef.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.
result = SemaRef.DefaultFunctionArrayLvalueConversion(collection);
ExprResult result = SemaRef.DefaultFunctionArrayLvalueConversion(collection);
if (result.isInvalid())
return ExprError();
collection = result.get();

View File

@ -14055,8 +14055,10 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(
// specified and it, along with any default template arguments,
// identifies a single function template specialization, then the
// template-id is an lvalue for the function template specialization.
FunctionTemplateDecl *FunctionTemplate
= cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl());
FunctionTemplateDecl *FunctionTemplate =
dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl());
if (!FunctionTemplate)
continue;
// C++ [over.over]p2:
// If the name is a function template, template argument deduction is

View File

@ -535,12 +535,7 @@ Sema::ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val) {
return ER;
};
ExprResult Converted = CorrectDelayedTyposInExpr(
Val, /*InitDecl=*/nullptr, /*RecoverUncorrectedTypos=*/false,
CheckAndFinish);
if (Converted.get() == Val.get())
Converted = CheckAndFinish(Val.get());
return Converted;
return CheckAndFinish(Val.get());
}
StmtResult
@ -2344,7 +2339,7 @@ StmtResult Sema::ActOnForEachLValueExpr(Expr *E) {
static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init,
SourceLocation Loc, int DiagID) {
if (Decl->getType()->isUndeducedType()) {
ExprResult Res = SemaRef.CorrectDelayedTyposInExpr(Init);
ExprResult Res = Init;
if (!Res.isUsable()) {
Decl->setInvalidDecl();
return true;
@ -3845,10 +3840,7 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
StmtResult
Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
Scope *CurScope) {
// Correct typos, in case the containing function returns 'auto' and
// RetValExp should determine the deduced type.
ExprResult RetVal = CorrectDelayedTyposInExpr(
RetValExp, nullptr, /*RecoverUncorrectedTypos=*/true);
ExprResult RetVal = RetValExp;
if (RetVal.isInvalid())
return StmtError();

View File

@ -782,11 +782,10 @@ ExprResult Sema::ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A,
ExprResult Sema::BuildCXXAssumeExpr(Expr *Assumption,
const IdentifierInfo *AttrName,
SourceRange Range) {
ExprResult Res = CorrectDelayedTyposInExpr(Assumption);
if (Res.isInvalid())
if (!Assumption)
return ExprError();
Res = CheckPlaceholderExpr(Res.get());
ExprResult Res = CheckPlaceholderExpr(Assumption);
if (Res.isInvalid())
return ExprError();

View File

@ -741,7 +741,6 @@ ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
if (!Pattern->containsUnexpandedParameterPack()) {
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
<< Pattern->getSourceRange();
CorrectDelayedTyposInExpr(Pattern);
return ExprError();
}
@ -1201,11 +1200,9 @@ ExprResult Sema::ActOnPackIndexingExpr(Scope *S, Expr *PackExpression,
SourceLocation RSquareLoc) {
bool isParameterPack = ::isParameterPack(PackExpression);
if (!isParameterPack) {
if (!PackExpression->containsErrors()) {
CorrectDelayedTyposInExpr(IndexExpr);
if (!PackExpression->containsErrors())
Diag(PackExpression->getBeginLoc(), diag::err_expected_name_of_pack)
<< PackExpression;
}
return ExprError();
}
ExprResult Res =
@ -1403,11 +1400,6 @@ ExprResult Sema::ActOnCXXFoldExpr(Scope *S, SourceLocation LParenLoc, Expr *LHS,
CheckFoldOperand(*this, LHS);
CheckFoldOperand(*this, RHS);
auto DiscardOperands = [&] {
CorrectDelayedTyposInExpr(LHS);
CorrectDelayedTyposInExpr(RHS);
};
// [expr.prim.fold]p3:
// In a binary fold, op1 and op2 shall be the same fold-operator, and
// either e1 shall contain an unexpanded parameter pack or e2 shall contain
@ -1415,7 +1407,6 @@ ExprResult Sema::ActOnCXXFoldExpr(Scope *S, SourceLocation LParenLoc, Expr *LHS,
if (LHS && RHS &&
LHS->containsUnexpandedParameterPack() ==
RHS->containsUnexpandedParameterPack()) {
DiscardOperands();
return Diag(EllipsisLoc,
LHS->containsUnexpandedParameterPack()
? diag::err_fold_expression_packs_both_sides
@ -1430,7 +1421,6 @@ ExprResult Sema::ActOnCXXFoldExpr(Scope *S, SourceLocation LParenLoc, Expr *LHS,
Expr *Pack = LHS ? LHS : RHS;
assert(Pack && "fold expression with neither LHS nor RHS");
if (!Pack->containsUnexpandedParameterPack()) {
DiscardOperands();
return Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
<< Pack->getSourceRange();
}

View File

@ -13121,12 +13121,6 @@ TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) {
return E;
}
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformTypoExpr(TypoExpr *E) {
return E;
}
template <typename Derived>
ExprResult TreeTransform<Derived>::TransformRecoveryExpr(RecoveryExpr *E) {
llvm::SmallVector<Expr *, 8> Children;

View File

@ -2310,10 +2310,6 @@ void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
E->setIsUnique(Record.readInt());
}
void ASTStmtReader::VisitTypoExpr(TypoExpr *E) {
llvm_unreachable("Cannot read TypoExpr nodes");
}
void ASTStmtReader::VisitRecoveryExpr(RecoveryExpr *E) {
VisitExpr(E);
unsigned NumArgs = Record.readInt();

View File

@ -2314,12 +2314,6 @@ void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
Code = serialization::EXPR_OPAQUE_VALUE;
}
void ASTStmtWriter::VisitTypoExpr(TypoExpr *E) {
VisitExpr(E);
// TODO: Figure out sane writer behavior for a TypoExpr, if necessary
llvm_unreachable("Cannot write TypoExpr nodes");
}
//===----------------------------------------------------------------------===//
// CUDA Expressions and Statements.
//===----------------------------------------------------------------------===//

View File

@ -1732,7 +1732,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::ExpressionTraitExprClass:
case Stmt::UnresolvedLookupExprClass:
case Stmt::UnresolvedMemberExprClass:
case Stmt::TypoExprClass:
case Stmt::RecoveryExprClass:
case Stmt::CXXNoexceptExprClass:
case Stmt::PackExpansionExprClass:

View File

@ -910,7 +910,8 @@ namespace CompoundLiterals {
constexpr int f2(int *x =(int[]){1,2,3}) {
return x[0];
}
constexpr int g = f2(); // Should evaluate to 1?
// Should evaluate to 1?
constexpr int g = f2(); // #g_decl
static_assert(g == 1, "");
// This example should be rejected because the lifetime of the compound
@ -1347,7 +1348,10 @@ namespace NTTP {
namespace UnaryOpError {
constexpr int foo() {
int f = 0;
++g; // both-error {{use of undeclared identifier 'g'}}
++g; // both-error {{use of undeclared identifier 'g'}} \
both-error {{cannot assign to variable 'g' with const-qualified type 'const int'}} \
both-note@#g_decl {{'CompoundLiterals::g' declared here}} \
both-note@#g_decl {{variable 'g' declared const here}}
return f;
}
}

View File

@ -23,13 +23,6 @@ int postfix_inc = a++;
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int'
int unary_address = &(a + 1);
// CHECK: VarDecl {{.*}} ternary 'int' cinit
// CHECK-NEXT: `-ConditionalOperator {{.*}}
// CHECK-NEXT: |-DeclRefExpr {{.*}} 'a'
// CHECK-NEXT: |-RecoveryExpr {{.*}}
// CHECK-NEXT: `-DeclRefExpr {{.*}} 'a'
int ternary = a ? undef : a;
void test1() {
// CHECK: `-RecoveryExpr {{.*}} contains-errors
// CHECK-NEXT: `-DeclRefExpr {{.*}} 'a' 'const int'
@ -91,12 +84,6 @@ void test3() {
// CHECK-NEXT: | `-DeclRefExpr {{.*}} '__builtin_classify_type'
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
(*__builtin_classify_type)(1);
extern void ext();
// CHECK: CallExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: |-DeclRefExpr {{.*}} 'ext'
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>'
ext(undef_var);
}
// Verify no crash.
@ -110,23 +97,6 @@ void test4() {
};
}
// Verify no crash
void test5_GH62711() {
// CHECK: VAArgExpr {{.*}} 'int' contains-errors
// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: | `-RecoveryExpr {{.*}} '<dependent type>' contains-errors
if (__builtin_va_arg(undef, int) << 1);
}
void test6_GH50244() {
double array[16];
// CHECK: UnaryExprOrTypeTraitExpr {{.*}} 'unsigned long' contains-errors sizeof
// CHECK-NEXT: `-CallExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: |-DeclRefExpr {{.*}} 'int ()'
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>'
sizeof array / sizeof foo(undef);
}
// No crash on DeclRefExpr that refers to ValueDecl with invalid initializers.
void test7() {
int b[] = {""()};

View File

@ -9,28 +9,6 @@ int some_func(int *);
// CHECK-NEXT: `-IntegerLiteral {{.*}} 123
// DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors
int invalid_call = some_func(123);
void test_invalid_call_1(int s) {
// CHECK: CallExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func'
// CHECK-NEXT: |-RecoveryExpr {{.*}} <col:13>
// CHECK-NEXT: `-BinaryOperator {{.*}}
// CHECK-NEXT: |-RecoveryExpr {{.*}}
// CHECK-NEXT: `-IntegerLiteral {{.*}} <col:28> 'int' 1
some_func(undef1, undef2+1);
// CHECK: BinaryOperator {{.*}} '<dependent type>' contains-errors '='
// CHECK-NEXT: |-DeclRefExpr {{.*}} 's'
// CHECK-NEXT: `-CallExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func'
// CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors
s = some_func(undef1);
// CHECK: VarDecl {{.*}} var 'int'
// CHECK-NEXT: `-CallExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func'
// CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors
int var = some_func(undef1);
}
int some_func2(int a, int b);
void test_invalid_call_2() {
@ -63,22 +41,6 @@ int ambig_func(float);
// DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors
int ambig_call = ambig_func(123);
// CHECK: VarDecl {{.*}} unresolved_call1
// CHECK-NEXT:`-RecoveryExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'bar'
// DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors
int unresolved_call1 = bar();
// CHECK: VarDecl {{.*}} unresolved_call2
// CHECK-NEXT:`-CallExpr {{.*}} contains-errors
// CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'bar'
// CHECK-NEXT: |-RecoveryExpr {{.*}} contains-errors
// CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}} 'baz'
// CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors
// CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'qux'
// DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors
int unresolved_call2 = bar(baz(), qux());
constexpr int a = 10;
// CHECK: VarDecl {{.*}} postfix_inc
@ -177,11 +139,6 @@ void test2(Foo2 f) {
f.overload(1);
}
// CHECK: |-AlignedAttr {{.*}} alignas
// CHECK-NEXT:| `-RecoveryExpr {{.*}} contains-errors
// CHECK-NEXT:| `-UnresolvedLookupExpr {{.*}} 'invalid'
struct alignas(invalid()) Aligned {};
auto f();
int f(double);
// CHECK: VarDecl {{.*}} unknown_type_call 'int'
@ -203,16 +160,6 @@ void InvalidInitalizer(int x) {
// CHECK-NEXT: `-InitListExpr
// CHECK-NEDT: `-DeclRefExpr {{.*}} 'x'
Bar a3{x};
// CHECK: `-VarDecl {{.*}} a4 'Bar'
// CHECK-NEXT: `-ParenListExpr {{.*}} 'NULL TYPE' contains-errors
// CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors
// CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'invalid'
Bar a4(invalid());
// CHECK: `-VarDecl {{.*}} a5 'Bar'
// CHECK-NEXT: `-InitListExpr {{.*}} contains-errors
// CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors
// CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'invalid'
Bar a5{invalid()};
// CHECK: `-VarDecl {{.*}} b1 'Bar'
// CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors
@ -231,51 +178,11 @@ void InvalidInitalizer(int x) {
// CHECK-NEXT: `-InitListExpr {{.*}} 'void'
// CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int'
Bar b4 = Bar{x};
// CHECK: `-VarDecl {{.*}} b5 'Bar'
// CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} 'Bar' contains-errors 'Bar'
// CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors
// CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'invalid'
Bar b5 = Bar(invalid());
// CHECK: `-VarDecl {{.*}} b6 'Bar'
// CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} 'Bar' contains-errors 'Bar'
// CHECK-NEXT: `-InitListExpr {{.*}} contains-errors
// CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors
// CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'invalid'
Bar b6 = Bar{invalid()};
// CHECK: RecoveryExpr {{.*}} 'Bar' contains-errors
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
Bar(1);
// CHECK: `-VarDecl {{.*}} var1
// CHECK-NEXT: `-BinaryOperator {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: |-RecoveryExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
int var1 = undef + 1;
}
void InitializerForAuto() {
// CHECK: `-VarDecl {{.*}} invalid a 'auto'
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'invalid'
auto a = invalid();
// CHECK: `-VarDecl {{.*}} invalid b 'auto'
// CHECK-NEXT: `-CallExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func'
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'invalid'
auto b = some_func(invalid());
decltype(ned);
// very bad initailizer: there is an unresolved typo expr internally, we just
// drop it.
// CHECK: `-VarDecl {{.*}} invalid unresolved_typo 'auto'
auto unresolved_typo = gned.*[] {};
}
// Verified that the generated call operator is invalid.
// CHECK: |-CXXMethodDecl {{.*}} invalid operator() 'auto () const -> auto'
using Escape = decltype([] { return undef(); }());
// CHECK: VarDecl {{.*}} NoCrashOnInvalidInitList
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>' contains-errors lvalue
@ -301,56 +208,8 @@ void ValueCategory() {
xvalue(); // call to a function (rvalue reference return type) yields an xvalue.
}
void InvalidCondition() {
// CHECK: IfStmt {{.*}}
// CHECK-NEXT: |-RecoveryExpr {{.*}} <col:7, col:15> '<dependent type>' contains-errors
// CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}} <col:7>
if (invalid()) {}
// CHECK: WhileStmt {{.*}}
// CHECK-NEXT: |-RecoveryExpr {{.*}} <col:10, col:18> '<dependent type>' contains-errors
// CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}} <col:10>
while (invalid()) {}
// CHECK: SwitchStmt {{.*}}
// CHECK-NEXT: |-RecoveryExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}} <col:10>
switch(invalid()) {
case 1:
break;
}
// FIXME: figure out why the type of ConditionalOperator is not int.
// CHECK: ConditionalOperator {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: |-RecoveryExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}}
// CHECK-NEXT: |-IntegerLiteral {{.*}} 'int' 1
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 2
invalid() ? 1 : 2;
}
void CtorInitializer() {
struct S{int m};
class MemberInit {
int x, y, z;
S s;
MemberInit() : x(invalid), y(invalid, invalid), z(invalid()), s(1,2) {}
// CHECK: CXXConstructorDecl {{.*}} MemberInit 'void ()'
// CHECK-NEXT: |-CXXCtorInitializer Field {{.*}} 'x' 'int'
// CHECK-NEXT: | `-ParenListExpr
// CHECK-NEXT: | `-RecoveryExpr {{.*}} '<dependent type>'
// CHECK-NEXT: |-CXXCtorInitializer Field {{.*}} 'y' 'int'
// CHECK-NEXT: | `-ParenListExpr
// CHECK-NEXT: | |-RecoveryExpr {{.*}} '<dependent type>'
// CHECK-NEXT: | `-RecoveryExpr {{.*}} '<dependent type>'
// CHECK-NEXT: |-CXXCtorInitializer Field {{.*}} 'z' 'int'
// CHECK-NEXT: | `-ParenListExpr
// CHECK-NEXT: | `-RecoveryExpr {{.*}} '<dependent type>'
// CHECK-NEXT: | `-UnresolvedLookupExpr {{.*}} '<overloaded function type>'
// CHECK-NEXT: |-CXXCtorInitializer Field {{.*}} 's' 'S'
// CHECK-NEXT: | `-RecoveryExpr {{.*}} 'S' contains-errors
// CHECK-NEXT: | |-IntegerLiteral {{.*}} 1
// CHECK-NEXT: | `-IntegerLiteral {{.*}} 2
};
class BaseInit : S {
BaseInit(float) : S("no match") {}
// CHECK: CXXConstructorDecl {{.*}} BaseInit 'void (float)'
@ -358,13 +217,6 @@ void CtorInitializer() {
// CHECK-NEXT: |-CXXCtorInitializer 'S'
// CHECK-NEXT: | `-RecoveryExpr {{.*}} 'S'
// CHECK-NEXT: | `-StringLiteral
BaseInit(double) : S(invalid) {}
// CHECK: CXXConstructorDecl {{.*}} BaseInit 'void (double)'
// CHECK-NEXT: |-ParmVarDecl
// CHECK-NEXT: |-CXXCtorInitializer 'S'
// CHECK-NEXT: | `-ParenListExpr
// CHECK-NEXT: | `-RecoveryExpr {{.*}} '<dependent type>'
};
class DelegatingInit {
DelegatingInit(float) : DelegatingInit("no match") {}
@ -373,13 +225,6 @@ void CtorInitializer() {
// CHECK-NEXT: |-CXXCtorInitializer 'DelegatingInit'
// CHECK-NEXT: | `-RecoveryExpr {{.*}} 'DelegatingInit'
// CHECK-NEXT: | `-StringLiteral
DelegatingInit(double) : DelegatingInit(invalid) {}
// CHECK: CXXConstructorDecl {{.*}} DelegatingInit 'void (double)'
// CHECK-NEXT: |-ParmVarDecl
// CHECK-NEXT: |-CXXCtorInitializer 'DelegatingInit'
// CHECK-NEXT: | `-ParenListExpr
// CHECK-NEXT: | `-RecoveryExpr {{.*}} '<dependent type>'
};
}
@ -423,65 +268,6 @@ void returnInitListFromVoid() {
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 8
}
void RecoveryExprForInvalidDecls(Unknown InvalidDecl) {
InvalidDecl + 1;
// CHECK: BinaryOperator {{.*}}
// CHECK-NEXT: |-RecoveryExpr {{.*}} '<dependent type>'
// CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'InvalidDecl' 'int'
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
InvalidDecl();
// CHECK: CallExpr {{.*}}
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>'
}
void InitializerOfInvalidDecl() {
int ValidDecl;
Unkown InvalidDecl = ValidDecl;
// CHECK: VarDecl {{.*}} invalid InvalidDecl
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'ValidDecl'
Unknown InvalidDeclWithInvalidInit = Invalid;
// CHECK: VarDecl {{.*}} invalid InvalidDeclWithInvalidInit
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NOT: `-TypoExpr
}
void RecoverToAnInvalidDecl() {
Unknown* foo; // invalid decl
goo; // the typo was correct to the invalid foo.
// Verify that RecoveryExpr has an inner DeclRefExpr.
// CHECK: RecoveryExpr {{.*}} '<dependent type>' contains-errors lvalue
// CHECK-NEXT: `-DeclRefExpr {{.*}} 'foo' 'int *'
}
void RecoveryToDoWhileStmtCond() {
// CHECK: FunctionDecl {{.*}} RecoveryToDoWhileStmtCond
// CHECK: `-DoStmt {{.*}}
// CHECK-NEXT: |-CompoundStmt {{.*}}
// CHECK-NEXT: `-BinaryOperator {{.*}} '<dependent type>' contains-errors '<'
// CHECK-NEXT: |-BinaryOperator {{.*}} '<dependent type>' contains-errors '+'
// CHECK-NEXT: | |-RecoveryExpr {{.*}} '<dependent type>' contains-errors lvalue
// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 1
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 10
do {} while (some_invalid_val + 1 < 10);
}
void RecoveryForStmtCond() {
// CHECK:FunctionDecl {{.*}} RecoveryForStmtCond
// CHECK-NEXT:`-CompoundStmt {{.*}}
// CHECK-NEXT: `-ForStmt {{.*}}
// CHECK-NEXT: |-DeclStmt {{.*}}
// CHECK-NEXT: | `-VarDecl {{.*}}
// CHECK-NEXT: | `-IntegerLiteral {{.*}} <col:16> 'int' 0
// CHECK-NEXT: |-<<<NULL>>>
// CHECK-NEXT: |-RecoveryExpr {{.*}} 'bool' contains-errors
// CHECK-NEXT: |-UnaryOperator {{.*}} 'int' lvalue prefix '++'
// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'i' 'int'
// CHECK-NEXT: `-CompoundStmt {{.*}}
for (int i = 0; i < invalid; ++i) {}
}
// Fix crash issue https://github.com/llvm/llvm-project/issues/112560.
// Make sure clang compiles the following code without crashing:

View File

@ -1,32 +0,0 @@
// RUN: not %clang_cc1 -triple x86_64-unknown-unknown -frecovery-ast -frecovery-ast-type -fblocks -ast-dump %s | FileCheck -strict-whitespace %s
@interface Foo
- (void)method:(int)n;
@end
void k(Foo *foo) {
// CHECK: ObjCMessageExpr {{.*}} 'void' contains-errors
// CHECK-CHECK: |-ImplicitCastExpr {{.*}} 'Foo *' <LValueToRValue>
// CHECK-CHECK: | `-DeclRefExpr {{.*}} 'foo'
// CHECK-CHECK: `-RecoveryExpr {{.*}}
[foo method:undef];
// CHECK: ImplicitCastExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: `-DeclRefExpr {{.*}} 'foo'
foo.undef;
}
// CHECK: |-VarDecl {{.*}} 'int (^)()' cinit
// CHECK-NEXT: | `-RecoveryExpr {{.*}} '<dependent type> (^)(void)' contains-errors lvalue
// CHECK-NEXT: | `-BlockExpr {{.*}} '<dependent type> (^)(void)'
// CHECK-NEXT: | `-BlockDecl {{.*}} invalid
int (^gh63863)() = ^() {
return undef;
};
// CHECK: `-BlockExpr {{.*}} 'int (^)(int, int)'
// CHECK-NEXT: `-BlockDecl {{.*}} invalid
int (^gh64005)(int, int) = ^(int, undefined b) {
return 1;
};

View File

@ -702,8 +702,7 @@ namespace cwg141 { // cwg141: 3.1
// cxx98-error@#cwg141-a {{lookup of 'S' in member access expression is ambiguous; using member of 'struct A'}}
// cxx98-note@#cwg141-A-S {{lookup in the object type 'struct A' refers here}}
// cxx98-note@#cwg141-S {{lookup from the current scope refers here}}
// expected-error@#cwg141-a {{no member named 'n' in 'cwg141::A::S<int>'; did you mean '::cwg141::S<int>::n'?}}
// expected-note@#cwg141-S {{'::cwg141::S<int>::n' declared here}}
// expected-error@#cwg141-a {{no member named 'n' in 'cwg141::A::S<int>'}}
// FIXME: we issue a useful diagnostic first, then some bogus ones.
b.f<int>();
// expected-error@-1 {{no member named 'f' in 'cwg141::B'}}

View File

@ -220,7 +220,6 @@ int x = cwg2640_a\N{abc});
int y = cwg2640_a\N{LOTUS});
// expected-error@-1 {{character <U+1FAB7> not allowed in an identifier}}
// expected-error@-2 {{use of undeclared identifier 'cwg2640_a🪷'}}
// expected-error@-3 {{extraneous ')' before ';'}}
} // namespace cwg2640
// cwg2642: na

View File

@ -51,7 +51,7 @@ void use_from_module_impl() {
(void)external_linkage_var;
(void)module_linkage_var;
(void)internal_linkage_class{}; // expected-error {{use of undeclared identifier 'internal_linkage_class'}} //expected-error{{}}
(void)internal_linkage_class{}; // expected-error {{use of undeclared identifier 'internal_linkage_class'}} // expected-note@* {{}}
(void)internal_linkage_var; // expected-error {{use of undeclared identifier 'internal_linkage_var'}}
}
@ -64,7 +64,7 @@ void use_from_module_impl() {
internal_linkage_fn(); // expected-error {{use of undeclared identifier 'internal_linkage_fn'}}
(void)external_linkage_class{};
(void)module_linkage_class{}; // expected-error {{undeclared identifier}} expected-error 0+{{}} // expected-note@* {{}}
(void)internal_linkage_class{}; // expected-error {{undeclared identifier}} expected-error 0+{{}}
(void)internal_linkage_class{}; // expected-error {{undeclared identifier}} expected-error 0+{{}} // expected-note@* {{}}
(void)external_linkage_var;
(void)module_linkage_var; // expected-error {{undeclared identifier}}
(void)internal_linkage_var; // expected-error {{undeclared identifier}}

View File

@ -1,137 +0,0 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: cp %s %t
// RUN: not %clang_cc1 -fixit -x c++ %t
// RUN: %clang_cc1 -fsyntax-only -pedantic -Werror -x c++ %t
// RUN: grep test_string %t
namespace std {
template<typename T> class basic_string { // expected-note 3{{'basic_string' declared here}}
public:
int find(const char *substr); // expected-note{{'find' declared here}}
static const int npos = -1; // expected-note{{'npos' declared here}}
};
typedef basic_string<char> string; // expected-note 2{{'string' declared here}}
}
namespace otherstd { // expected-note 2{{'otherstd' declared here}} \
// expected-note{{namespace 'otherstd' defined here}}
using namespace std;
}
using namespace std;
other_std::strng str1; // expected-error{{use of undeclared identifier 'other_std'; did you mean 'otherstd'?}} \
// expected-error{{no type named 'strng' in namespace 'otherstd'; did you mean 'string'?}}
tring str2; // expected-error{{unknown type name 'tring'; did you mean 'string'?}}
::other_std::string str3; // expected-error{{no member named 'other_std' in the global namespace; did you mean 'otherstd'?}}
float area(float radius, // expected-note{{'radius' declared here}}
float pi) {
return radious * pi; // expected-error{{did you mean 'radius'?}}
}
using namespace othestd; // expected-error{{no namespace named 'othestd'; did you mean 'otherstd'?}}
namespace blargh = otherstd; // expected-note 3{{namespace 'blargh' defined here}}
using namespace ::blarg; // expected-error{{no namespace named 'blarg' in the global namespace; did you mean 'blargh'?}}
namespace wibble = blarg; // expected-error{{no namespace named 'blarg'; did you mean 'blargh'?}}
namespace wobble = ::blarg; // expected-error{{no namespace named 'blarg' in the global namespace; did you mean 'blargh'?}}
bool test_string(std::string s) {
basc_string<char> b1; // expected-error{{no template named 'basc_string'; did you mean 'basic_string'?}}
std::basic_sting<char> b2; // expected-error{{no template named 'basic_sting' in namespace 'std'; did you mean 'basic_string'?}}
(void)b1;
(void)b2;
return s.fnd("hello") // expected-error{{no member named 'fnd' in 'std::basic_string<char>'; did you mean 'find'?}}
== std::string::pos; // expected-error{{no member named 'pos' in 'std::basic_string<char>'; did you mean 'npos'?}}
}
struct Base { };
struct Derived : public Base { // expected-note{{base class 'Base' specified here}}
int member; // expected-note 3{{'member' declared here}}
Derived() : base(), // expected-error{{initializer 'base' does not name a non-static data member or base class; did you mean the base class 'Base'?}}
ember() { } // expected-error{{initializer 'ember' does not name a non-static data member or base class; did you mean the member 'member'?}}
int getMember() const {
return ember; // expected-error{{use of undeclared identifier 'ember'; did you mean 'member'?}}
}
int &getMember();
};
int &Derived::getMember() {
return ember; // expected-error{{use of undeclared identifier 'ember'; did you mean 'member'?}}
}
typedef int Integer; // expected-note{{'Integer' declared here}}
int global_value; // expected-note{{'global_value' declared here}}
int foo() {
integer * i = 0; // expected-error{{unknown type name 'integer'; did you mean 'Integer'?}}
unsinged *ptr = 0; // expected-error{{use of undeclared identifier 'unsinged'; did you mean 'unsigned'?}}
return *i + *ptr + global_val; // expected-error{{use of undeclared identifier 'global_val'; did you mean 'global_value'?}}
}
namespace nonstd {
typedef std::basic_string<char> yarn; // expected-note 2 {{'nonstd::yarn' declared here}}
int narf; // expected-note{{'nonstd::narf' declared here}}
}
yarn str4; // expected-error{{unknown type name 'yarn'; did you mean 'nonstd::yarn'?}}
wibble::yarn str5; // expected-error{{no type named 'yarn' in namespace 'otherstd'; did you mean 'nonstd::yarn'?}}
namespace another {
template<typename T> class wide_string {}; // expected-note {{'another::wide_string' declared here}}
}
int poit() {
nonstd::basic_string<char> str; // expected-error{{no template named 'basic_string' in namespace 'nonstd'; did you mean simply 'basic_string'?}}
nonstd::wide_string<char> str2; // expected-error{{no template named 'wide_string' in namespace 'nonstd'; did you mean 'another::wide_string'?}}
return wibble::narf; // expected-error{{no member named 'narf' in namespace 'otherstd'; did you mean 'nonstd::narf'?}}
}
namespace check_bool {
void f() {
Bool b; // expected-error{{use of undeclared identifier 'Bool'; did you mean 'bool'?}}
}
}
namespace outr {
}
namespace outer {
namespace inner { // expected-note{{'outer::inner' declared here}} \
// expected-note{{namespace 'outer::inner' defined here}} \
// expected-note{{'inner' declared here}}
int i;
}
}
using namespace outr::inner; // expected-error{{no namespace named 'inner' in namespace 'outr'; did you mean 'outer::inner'?}}
void func() {
outr::inner::i = 3; // expected-error{{no member named 'inner' in namespace 'outr'; did you mean 'outer::inner'?}}
outer::innr::i = 4; // expected-error{{no member named 'innr' in namespace 'outer'; did you mean 'inner'?}}
}
struct base {
};
struct derived : base {
int i;
};
void func2() {
derived d;
// FIXME: we should offer a fix here. We do if the 'i' is misspelled, but we don't do name qualification changes
// to replace base::i with derived::i as we would for other qualified name misspellings.
// d.base::i = 3;
}
class A {
void bar(int);
};
void bar(int, int); // expected-note{{'::bar' declared here}}
void A::bar(int x) {
bar(x, 5); // expected-error{{too many arguments to function call, expected 1, have 2; did you mean '::bar'?}}
}

View File

@ -1,10 +0,0 @@
void f() {
auto foo = bar;
switch(foo) {
case x:
break;
}
}
// RUN: not %clang_cc1 -fsyntax-only -fno-recovery-ast -code-completion-at=%s:4:10 %s | FileCheck %s -allow-empty
// CHECK-NOT: COMPLETION: foo

View File

@ -1,27 +1,12 @@
// RUN: c-index-test -test-load-source all -fspell-checking %s 2> %t
// RUN: c-index-test -test-load-source all -fspell-checking %s 2> %t
// RUN: FileCheck %s < %t
struct X {
int wibble;
};
#define MACRO(X) X
void f(struct X *x) {
// CHECK: error: no member named 'wobble' in 'struct X'; did you mean 'wibble'?
// CHECK: FIX-IT: Replace [13:12 - 13:18] with "wibble"
// CHECK: note: 'wibble' declared here
MACRO(x->wobble = 17);
// CHECK: error: no member named 'wabble' in 'struct X'; did you mean 'wibble'?
// CHECK: FIX-IT: Replace [17:6 - 17:12] with "wibble"
// CHECK: note: 'wibble' declared here
x->wabble = 17;
}
int printf(const char *restrict, ...);
void f2() {
unsigned long index;
// CHECK: warning: format specifies type 'int' but the argument has type 'unsigned long'
// CHECK: FIX-IT: Replace [26:17 - 26:19] with "%lu"
// CHECK: FIX-IT: Replace [11:17 - 11:19] with "%lu"
MACRO(printf("%d", index));
}

View File

@ -27,13 +27,13 @@
// no-warning@* {{ignoring '-fno-raw-string-literals'}}
void f() {
(void) R"foo()foo"; // unsupported-error {{use of undeclared identifier 'R'}} cxx-unsupported-error {{expected ';' after expression}}
(void) LR"foo()foo"; // unsupported-error {{use of undeclared identifier 'LR'}} cxx-unsupported-error {{expected ';' after expression}}
(void) R"foo()foo"; // unsupported-error {{use of undeclared identifier 'R'}}
(void) LR"foo()foo"; // unsupported-error {{use of undeclared identifier 'LR'}}
#ifdef UNICODE
(void) uR"foo()foo"; // unsupported-error {{use of undeclared identifier 'uR'}} cxx-unsupported-error {{expected ';' after expression}}
(void) u8R"foo()foo"; // unsupported-error {{use of undeclared identifier 'u8R'}} cxx-unsupported-error {{expected ';' after expression}}
(void) UR"foo()foo"; // unsupported-error {{use of undeclared identifier 'UR'}} cxx-unsupported-error {{expected ';' after expression}}
(void) uR"foo()foo"; // unsupported-error {{use of undeclared identifier 'uR'}}
(void) u8R"foo()foo"; // unsupported-error {{use of undeclared identifier 'u8R'}}
(void) UR"foo()foo"; // unsupported-error {{use of undeclared identifier 'UR'}}
#endif
}

View File

@ -7,11 +7,9 @@
void foo(void) {
XYZLogEvent(xyzRiskyCloseOpenParam, xyzRiskyCloseOpenParam); // expected-error {{call to undeclared function 'XYZLogEvent'; ISO C99 and later do not support implicit function declarations}} \
expected-error {{declaration of 'XYZLogEvent' must be imported}} \
expected-error {{declaration of 'xyzRiskyCloseOpenParam' must be imported from module 'NCI.A'}} \
expected-error {{declaration of 'xyzRiskyCloseOpenParam' must be imported from module 'NCI.A'}}
}
// expected-note@Inputs/diagnose-missing-import/a.h:5 {{declaration here is not visible}}
// expected-note@Inputs/diagnose-missing-import/a.h:5 {{declaration here is not visible}}
// expected-note@Inputs/diagnose-missing-import/a.h:6 {{declaration here is not visible}}

View File

@ -83,7 +83,7 @@ const int var;
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind(score cpu)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<invalid>'); score ignored}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device = {kind(score(ibm) }) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<recovery-expr>()'); score ignored}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp begin declare variant match(device = {kind(score(ibm) }) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<invalid>'); score ignored}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind(score(2 gpu)}) // expected-error {{expected ')'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('2'); score ignored}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{to match this '('}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp end declare variant

View File

@ -69,7 +69,7 @@ class Class2 : public Class1<T> {
#pragma omp declare reduction(fun77 : long : omp_out += omp_in) initializer(omp_priv Class2 < int > ()) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp declare reduction(fun8 : long : omp_out += omp_in) initializer(omp_priv 23) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp declare reduction(fun88 : long : omp_out += omp_in) initializer(omp_priv 23)) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{extra tokens at the end of '#pragma omp declare reduction' are ignored}}
#pragma omp declare reduction(fun9 : long : omp_out += omp_priv) initializer(omp_in = 23) // expected-error {{use of undeclared identifier 'omp_priv'; did you mean 'omp_in'?}} expected-note {{'omp_in' declared here}}
#pragma omp declare reduction(fun9 : long : omp_out += omp_priv) initializer(omp_in = 23) // expected-error {{use of undeclared identifier 'omp_priv'}}
#pragma omp declare reduction(fun10 : long : omp_out += omp_in) initializer(omp_priv = 23)
template <typename T>

View File

@ -11,7 +11,7 @@ int foo(void);
#pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}}
#pragma omp declare variant( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp declare variant(foo // expected-error {{expected ')'}} omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}} expected-note {{to match this '('}}
#pragma omp declare variant(x) // expected-error {{use of undeclared identifier 'x'}} omp50-error {{expected 'match' clause on}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
#pragma omp declare variant(x) // expected-error {{use of undeclared identifier 'x'}}
#pragma omp declare variant(foo) // omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foo) // omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foo) xxx // omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
@ -42,7 +42,7 @@ int foo(void);
#pragma omp declare variant(foo) match(device={kind(}) // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foo) match(device={kind()}) // expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}}
#pragma omp declare variant(foo) match(device={kind(score cpu)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<invalid>'); score ignored}}
#pragma omp declare variant(foo) match(device = {kind(score(ibm) }) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<recovery-expr>()'); score ignored}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foo) match(device = {kind(score(ibm) }) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<invalid>'); score ignored}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foo) match(device={kind(score(2 gpu)}) // expected-error {{expected ')'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('2'); score ignored}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{to match this '('}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foo) match(device={kind(score(foo()) ibm)}) // expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('foo()'); score ignored}} expected-warning {{'ibm' is not a valid context property for the context selector 'kind' and the context set 'device'; property ignored}} expected-note {{try 'match(implementation={vendor(ibm)})'}} expected-note {{the ignored property spans until here}}
#pragma omp declare variant(foo) match(device={kind(score(5): host), kind(llvm)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('5'); score ignored}} expected-warning {{the context selector 'kind' was used already in the same 'omp declare variant' directive; selector ignored}} expected-note {{the previous context selector 'kind' used here}} expected-note {{the ignored selector spans until here}}
@ -56,7 +56,7 @@ int foo(void);
#pragma omp declare variant(foo) match(target_device={device_num}) // expected-warning {{the context selector 'device_num' in context set 'target_device' requires a context property defined in parentheses; selector ignored}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foo) match(target_device={device_num()}) // expected-error {{expected expression}}
#pragma omp declare variant(foo) match(target_device={device_num(-1)}) // expected-error {{argument to 'device_num' clause must be a non-negative integer value}}
#pragma omp declare variant(foo) match(target_device={device_num(abc)}) // expected-error {{expected expression}} expected-error {{use of undeclared identifier 'abc'}}
#pragma omp declare variant(foo) match(target_device={device_num(abc)}) // expected-error {{use of undeclared identifier 'abc'}}
int bar(void);

View File

@ -16,7 +16,7 @@ T foofoo();
#pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}}
#pragma omp declare variant( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp declare variant(foo // expected-error {{expected ')'}} omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}} expected-note {{to match this '('}}
#pragma omp declare variant(x) // expected-error {{use of undeclared identifier 'x'}} omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
#pragma omp declare variant(x) // expected-error {{use of undeclared identifier 'x'}}
#pragma omp declare variant(foo) // omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foofoo <int>) // omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foofoo <int>) xxx // omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
@ -57,7 +57,7 @@ int bar();
#pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}}
#pragma omp declare variant( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp declare variant(foofoo <T> // expected-error {{expected ')'}} omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}} expected-note {{to match this '('}}
#pragma omp declare variant(x) // expected-error {{use of undeclared identifier 'x'}} omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
#pragma omp declare variant(x) // expected-error {{use of undeclared identifier 'x'}}
#pragma omp declare variant(foo) // omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foofoo) // omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foofoo <T>) // omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}

View File

@ -113,9 +113,11 @@ int main(int argc, char **argv) {
// Check parsing with two modifiers.
// lt51-warning@+1 {{missing ':' after ) - ignoring}}
#pragma omp target update to(mapper(id), present: s)
// lt51-error@+3 {{use of undeclared identifier 'present'}}
// lt51-error@+2 {{use of undeclared identifier 'id'}}
// lt51-error@+1 {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
// lt51-error@+5 {{use of undeclared identifier 'present'}}
// lt51-error@+4 {{use of undeclared identifier 'id'}}
// lt51-error@+3 {{expected ',' or ')' in 'to' clause}}
// lt51-error@+2 {{expected ')'}}
// lt51-note@+1 {{to match this '('}}
#pragma omp target update to(present, mapper(id): s)
// lt51-warning@+1 {{missing ':' after ) - ignoring}}
#pragma omp target update to(mapper(id) present: s)
@ -141,10 +143,9 @@ int main(int argc, char **argv) {
#pragma omp target update to(present,,: s)
// lt51-warning@+1 {{missing ':' after ) - ignoring}}
#pragma omp target update to(mapper(id), present,: s)
// lt51-error@+4 {{use of undeclared identifier 'present'}}
// lt51-error@+3 {{use of undeclared identifier 'id'}}
// lt51-error@+2 {{expected expression}}
// lt51-error@+1 {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
// lt51-error@+3 {{use of undeclared identifier 'present'}}
// lt51-error@+2 {{use of undeclared identifier 'id'}}
// lt51-error@+1 {{expected expression}}
#pragma omp target update to(present, mapper(id),: s)
#pragma omp target update from(m) allocate(m) // expected-error {{unexpected OpenMP clause 'allocate' in directive '#pragma omp target update'}}

View File

@ -3,7 +3,7 @@
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-unknown-linux-gnu -verify=expected,cxx2c,post2b -fcxx-exceptions
// RUN: not %clang_cc1 -std=c++17 %s -triple x86_64-unknown-linux-gnu -emit-llvm-only -fcxx-exceptions
struct S { int a, b, c; };
struct S { int a, b, c; }; // expected-note 2 {{'S::a' declared here}}
// A simple-declaration can be a decompsition declaration.
namespace SimpleDecl {
@ -32,7 +32,7 @@ namespace ForRangeDecl {
namespace OtherDecl {
// A parameter-declaration is not a simple-declaration.
// This parses as an array declaration.
void f(auto [a, b, c]); // cxx17-error {{'auto' not allowed in function prototype}} expected-error {{'a'}}
void f(auto [a, b, c]); // cxx17-error {{'auto' not allowed in function prototype}} expected-error 1+{{'a'}}
void g() {
// A condition is allowed as a Clang extension.
@ -46,7 +46,7 @@ namespace OtherDecl {
// An exception-declaration is not a simple-declaration.
try {}
catch (auto [a, b, c]) {} // expected-error {{'auto' not allowed in exception declaration}} expected-error {{'a'}}
catch (auto [a, b, c]) {} // expected-error {{'auto' not allowed in exception declaration}} expected-error 1+{{'a'}}
}
// A member-declaration is not a simple-declaration.

View File

@ -37,14 +37,14 @@ template<int ...N> int bad12() { return (... N); } // expected-error {{expected
template<typename ...T> void as_operand_of_cast(int a, T ...t) {
return
(int)(a + ... + undeclared_junk) + // expected-error {{undeclared}} expected-error {{does not contain any unexpanded}}
(int)(a + ... + undeclared_junk) + // expected-error {{undeclared}}
(int)(t + ... + undeclared_junk) + // expected-error {{undeclared}}
(int)(... + undeclared_junk) + // expected-error {{undeclared}} expected-error {{does not contain any unexpanded}}
(int)(... + undeclared_junk) + // expected-error {{undeclared}}
(int)(undeclared_junk + ...) + // expected-error {{undeclared}}
(int)(a + ...) + // expected-error {{does not contain any unexpanded}}
(int)(a, ...) + // expected-error {{does not contain any unexpanded}}
(int)(..., a) + // expected-error {{does not contain any unexpanded}}
(int)(a, ..., undeclared_junk) + // expected-error {{undeclared}} expected-error {{does not contain any unexpanded}}
(int)(a, ..., undeclared_junk) + // expected-error {{undeclared}}
(int)(t, ...) +
(int)(..., t) +
(int)(t, ..., a);

View File

@ -69,7 +69,8 @@ template <typename... T>
requires( ); // expected-error {{expected expression}}
struct SS {
void f( ) {
(*p).~T...[](); // expected-error {{use of undeclared identifier 'p'}}
(*p).~T...[](); // expected-error {{use of undeclared identifier 'p'}} \
expected-error {{undeclared identifier 'T' in destructor name}}
}
};
}

View File

@ -21,6 +21,5 @@ MyList * el;
static int test7(id keys) {
for (id key; in keys) ; // expected-error {{use of undeclared identifier 'in'}} \
// expected-error {{expected ';' in 'for' statement specifier}}
for (id key; in keys) ; // expected-error {{use of undeclared identifier 'in'}}
}

View File

@ -39,23 +39,17 @@ void atomic_types_test(void) {
// expected-error@-11 {{use of undeclared identifier 'atomic_ulong'}}
// expected-error@-11 {{use of undeclared identifier 'atomic_double'}}
#if defined(LANG_VER_OK)
// expected-error@-15 {{expected ';' after expression}}
// expected-error@-16 {{use of undeclared identifier 'l'}}
// expected-error@-16 {{expected ';' after expression}}
// expected-error@-17 {{use of undeclared identifier 'ul'}}
#endif
#if !defined(LANG_VER_OK) || defined(__SPIR64__)
// expected-error@-18 {{use of undeclared identifier 'atomic_size_t'}}
// expected-error@-16 {{use of undeclared identifier 'atomic_ptrdiff_t'}}
// expected-error@-14 {{use of undeclared identifier 'atomic_size_t'}}
// expected-error@-12 {{use of undeclared identifier 'atomic_ptrdiff_t'}}
#if !defined(LANG_VER_OK)
// expected-error@-20 {{use of undeclared identifier 'atomic_intptr_t'}}
// expected-error@-20 {{use of undeclared identifier 'atomic_uintptr_t'}}
// expected-error@-16 {{use of undeclared identifier 'atomic_intptr_t'}}
// expected-error@-16 {{use of undeclared identifier 'atomic_uintptr_t'}}
#else
// expected-error@-24 {{expected ';' after expression}}
// expected-error@-25 {{use of undeclared identifier 's'}}
// expected-error@-25 {{unknown type name 'atomic_intptr_t'; did you mean 'atomic_int'?}}
// expected-error@-19 {{unknown type name 'atomic_intptr_t'; did you mean 'atomic_int'?}}
// expected-note@* {{'atomic_int' declared here}}
// expected-error@-26 {{unknown type name 'atomic_uintptr_t'; did you mean 'atomic_uint'?}}
// expected-error@-20 {{unknown type name 'atomic_uintptr_t'; did you mean 'atomic_uint'?}}
// expected-note@* {{'atomic_uint' declared here}}
#endif
#endif

View File

@ -11,7 +11,7 @@ float test2241[2] = {
static void f (char * (*g) (char **, int), char **p, ...) {
char *s;
va_list v; // expected-error {{identifier}}
s = g (p, __builtin_va_arg(v, int)); // expected-error {{identifier}}
s = g (p, __builtin_va_arg(v, int)); // expected-error {{identifier}} expected-error {{extraneous ')' before ';'}}
}

View File

@ -104,7 +104,7 @@ void test9(int x) { // expected-note {{'x' declared here}}
expected-error {{expected expression}}
8:: x; // expected-error {{expected ';' after expression}} \
expected-error {{no member named 'x' in the global namespace; did you mean simply 'x'?}} \
expected-warning {{expression result unused}}
expected-warning 2 {{expression result unused}}
9:: :y; // expected-error {{expected ';' after expression}} \
expected-error {{expected unqualified-id}} \
expected-warning {{expression result unused}}

View File

@ -1,9 +1,9 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
namespace c { double xxx; } // expected-note{{'c::xxx' declared here}}
namespace c { double xxx; }
namespace d { float xxx; }
namespace z { namespace xxx {} }
void crash() {
switch (xxx) {} // expected-error{{use of undeclared identifier 'xxx'; did you mean }}
switch (xxx) {} // expected-error{{use of undeclared identifier 'xxx'}}
}

View File

@ -1,8 +1,8 @@
// RUN: %clang_cc1 %s -verify -fopenacc
namespace NS {
static char* NSArray;// expected-note{{declared here}}
static int NSInt;// expected-note 2{{declared here}}
static char* NSArray; // expected-note {{'NS::NSArray' declared here}}
static int NSInt; // expected-note 2 {{'NS::NSInt' declared here}}
}
char *getArrayPtr();
template<typename T, int I>
@ -21,17 +21,17 @@ void func() {
}
for (int i = 0; i < 10; ++i) {
// expected-error@+1{{use of undeclared identifier 'NSArray'; did you mean 'NS::NSArray'}}
// expected-error@+1{{use of undeclared identifier 'NSArray'}}
#pragma acc cache(NSArray[NS::NSInt : NS::NSInt])
}
for (int i = 0; i < 10; ++i) {
// expected-error@+1{{use of undeclared identifier 'NSInt'; did you mean 'NS::NSInt'}}
// expected-error@+1{{use of undeclared identifier 'NSInt'}}
#pragma acc cache(NS::NSArray[NSInt : NS::NSInt])
}
for (int i = 0; i < 10; ++i) {
// expected-error@+1{{use of undeclared identifier 'NSInt'; did you mean 'NS::NSInt'}}
// expected-error@+1{{use of undeclared identifier 'NSInt'}}
#pragma acc cache(NS::NSArray[NS::NSInt : NSInt])
}
}

View File

@ -347,9 +347,7 @@ void SelfUpdate() {
#pragma acc update host(s) self
for(int i = 0; i < 5;++i) {}
// expected-error@+3{{use of undeclared identifier 'zero'}}
// expected-error@+2{{expected ','}}
// expected-error@+1{{expected expression}}
// expected-error@+1{{use of undeclared identifier 'zero'}}
#pragma acc update self(zero : s.array[s.value : 5], s.value), if_present
for(int i = 0; i < 5;++i) {}
@ -453,8 +451,6 @@ void VarListClauses() {
#pragma acc parallel copy(always, alwaysin, always: HasMem.MemArr[3:]) self
for(int i = 0; i < 5;++i) {}
// expected-error@+3{{use of undeclared identifier 'always'}}
// expected-error@+2{{use of undeclared identifier 'alwaysin'}}
// expected-error@+1{{use of undeclared identifier 'always'}}
#pragma acc parallel copy(always, alwaysin, always, HasMem.MemArr[3:]) self
for(int i = 0; i < 5;++i) {}
@ -591,8 +587,7 @@ void VarListClauses() {
#pragma acc serial copyout(zero : s.array[s.value : 5], s.value), self
for(int i = 0; i < 5;++i) {}
// expected-error@+2{{use of undeclared identifier 'zero'}}
// expected-error@+1{{expected ','}}
// expected-error@+1{{use of undeclared identifier 'zero'}}
#pragma acc serial copyout(zero s.array[s.value : 5], s.value), self
for(int i = 0; i < 5;++i) {}
@ -608,8 +603,7 @@ void VarListClauses() {
#pragma acc serial copyout(invalid:s.array[s.value : 5], s.value), self
for(int i = 0; i < 5;++i) {}
// expected-error@+2{{use of undeclared identifier 'invalid'}}
// expected-error@+1{{expected ','}}
// expected-error@+1{{use of undeclared identifier 'invalid'}}
#pragma acc serial copyout(invalid s.array[s.value : 5], s.value), self
for(int i = 0; i < 5;++i) {}
@ -657,8 +651,7 @@ void VarListClauses() {
#pragma acc serial create(zero : s.array[s.value : 5], s.value), self
for(int i = 0; i < 5;++i) {}
// expected-error@+2{{use of undeclared identifier 'zero'}}
// expected-error@+1{{expected ','}}
// expected-error@+1{{use of undeclared identifier 'zero'}}
#pragma acc serial create(zero s.array[s.value : 5], s.value), self
for(int i = 0; i < 5;++i) {}
@ -674,8 +667,7 @@ void VarListClauses() {
#pragma acc serial create(invalid:s.array[s.value : 5], s.value), self
for(int i = 0; i < 5;++i) {}
// expected-error@+2{{use of undeclared identifier 'invalid'}}
// expected-error@+1{{expected ','}}
// expected-error@+1{{use of undeclared identifier 'invalid'}}
#pragma acc serial create(invalid s.array[s.value : 5], s.value), self
for(int i = 0; i < 5;++i) {}
@ -700,8 +692,7 @@ void VarListClauses() {
#pragma acc serial copyin(readonly : s.array[s.value : 5], s.value), self
for(int i = 0; i < 5;++i) {}
// expected-error@+2{{use of undeclared identifier 'readonly'}}
// expected-error@+1{{expected ','}}
// expected-error@+1{{use of undeclared identifier 'readonly'}}
#pragma acc serial copyin(readonly s.array[s.value : 5], s.value), self
for(int i = 0; i < 5;++i) {}
@ -717,8 +708,7 @@ void VarListClauses() {
#pragma acc serial copyin(invalid:s.array[s.value : 5], s.value), self
for(int i = 0; i < 5;++i) {}
// expected-error@+2{{use of undeclared identifier 'invalid'}}
// expected-error@+1{{expected ','}}
// expected-error@+1{{use of undeclared identifier 'invalid'}}
#pragma acc serial copyin(invalid s.array[s.value : 5], s.value), self
for(int i = 0; i < 5;++i) {}

View File

@ -18,13 +18,13 @@ namespace NS {
#pragma acc routine(NS::foo) seq
// expected-error@+2{{use of undeclared identifier 'templ'; did you mean 'NS::templ'?}}
// expected-error@+1{{OpenACC routine name 'NS::templ' names a set of overloads}}
// expected-error@+1{{OpenACC routine name 'templ' names a set of overloads}}
#pragma acc routine(templ) seq
// expected-error@+1{{OpenACC routine name 'NS::templ' names a set of overloads}}
#pragma acc routine(NS::templ) seq
// expected-error@+2{{use of undeclared identifier 'templ'; did you mean 'NS::templ'?}}
// expected-error@+1{{OpenACC routine name 'NS::templ' names a set of overloads}}
// expected-error@+1{{OpenACC routine name 'templ<int>' names a set of overloads}}
#pragma acc routine(templ<int>) seq
// expected-error@+1{{OpenACC routine name 'NS::templ<int>' names a set of overloads}}
#pragma acc routine(NS::templ<int>) seq

View File

@ -85,19 +85,16 @@ void func() {
#pragma acc parallel wait (devnum: i + j:queues:) clause-list
{}
// expected-error@+4{{use of undeclared identifier 'devnum'}}
// expected-error@+3{{expected ','}}
// expected-error@+3{{use of undeclared identifier 'devnum'}}
// expected-error@+2{{expected ')'}}
// expected-note@+1{{to match this '('}}
#pragma acc parallel wait (queues:devnum: i + j
{}
// expected-error@+2{{expected ','}}
// expected-error@+1{{use of undeclared identifier 'devnum'}}
#pragma acc parallel wait (queues:devnum: i + j)
{}
// expected-error@+3{{expected ','}}
// expected-error@+2{{use of undeclared identifier 'devnum'}}
// expected-error@+1{{invalid OpenACC clause 'clause'}}
#pragma acc parallel wait (queues:devnum: i + j) clause-list

View File

@ -68,18 +68,15 @@ void func() {
// expected-error@+1{{invalid OpenACC clause 'clause'}}
#pragma acc wait (devnum: i + j:queues:) clause-list
// expected-error@+4{{use of undeclared identifier 'devnum'}}
// expected-error@+3{{expected ','}}
// expected-error@+3{{use of undeclared identifier 'devnum'}}
// expected-error@+2{{expected ')'}}
// expected-note@+1{{to match this '('}}
#pragma acc wait (queues:devnum: i + j
// expected-error@+2{{use of undeclared identifier 'devnum'}}
// expected-error@+1{{expected ','}}
// expected-error@+1{{use of undeclared identifier 'devnum'}}
#pragma acc wait (queues:devnum: i + j)
// expected-error@+3{{use of undeclared identifier 'devnum'}}
// expected-error@+2{{expected ','}}
// expected-error@+2{{use of undeclared identifier 'devnum'}}
// expected-error@+1{{invalid OpenACC clause 'clause'}}
#pragma acc wait (queues:devnum: i + j) clause-list

View File

@ -5,9 +5,9 @@ struct spinlock_t {
} audit_skb_queue;
void fn1(void) {
audit_skb_queue = (lock); // expected-error {{use of undeclared identifier 'lock'; did you mean 'long'?}}
} // expected-error@-1 {{assigning to 'struct spinlock_t' from incompatible type '<overloaded function type>'}}
audit_skb_queue = (lock); // expected-error {{use of undeclared identifier 'lock'}}
}
void fn2(void) {
audit_skb_queue + (lock); // expected-error {{use of undeclared identifier 'lock'; did you mean 'long'?}}
} // expected-error@-1 {{reference to overloaded function could not be resolved; did you mean to call it?}}
audit_skb_queue + (lock); // expected-error {{use of undeclared identifier 'lock'}}
}

View File

@ -17,5 +17,4 @@ void a(void) {
check(__builtin_fpclassify(0,0,0,0,0, (invalid))); // expected-error{{use of undeclared identifier 'invalid'}}
check(__builtin_fpclassify(0,0,0,0,0, (inf))); // expected-error{{use of undeclared identifier 'inf'}}
// expected-error@-1{{reference to overloaded function could not be resolved}}
}

View File

@ -0,0 +1,18 @@
// RUN: %clang_cc1 -std=c23 -fsyntax-only -verify %s
void GH139913(...);
void GH139913_test() {
GH139913(CONCAT(foo, )); // expected-error {{use of undeclared identifier 'CONCAT'}} \
expected-error {{use of undeclared identifier 'foo'}} \
expected-error {{expected expression}}
}
struct GH137867 {
char value;
};
void GH137867_test() {
_Atomic(struct GH137867) t;
while (!atomic_load(&t.value)->value) // expected-error {{use of undeclared identifier 'atomic_load'}} \
expected-error {{accessing a member of an atomic structure or union is undefined behavior}}
;
}

View File

@ -0,0 +1,18 @@
// RUN: %clang_cc1 -fsyntax-only -fblocks -ffixed-point -verify %s
void GH137860_test(void) {
struct S {
char h;
};
_Atomic struct S s = { .h = UINT8_MIN }; // expected-error {{use of undeclared identifier 'UINT8_MIN'}}
__c11_atomic_fetch_add(&s.h, UINT8_MIN); // expected-error {{use of undeclared identifier 'UINT8_MIN'}} \
expected-error {{accessing a member of an atomic structure or union is undefined behavior}}
}
int (^GH69470) (int i, int j) = ^(int i, int j)
{ return i / j; }/ j; // expected-error {{use of undeclared identifier 'j'}}
void GH69874(void) {
*a = (a_struct){0}; // expected-error {{use of undeclared identifier 'a'}} \
expected-error {{use of undeclared identifier 'a_struct'}}
}

View File

@ -20,10 +20,12 @@ class Z {
// Should be able to evaluate sizeof without crashing.
static_assert(sizeof(Z) == 1, "No valid members");
constexpr int N = undef; // expected-error {{use of undeclared identifier}}
constexpr int N = undef; // expected-error {{use of undeclared identifier}} \
expected-note {{declared here}}
template<int a>
class ABC {};
class T {
ABC<N> abc;
ABC<N> abc; // expected-error {{non-type template argument is not a constant expression}} \
expected-note {{initializer of 'N' is unknown}}
};
static_assert(sizeof(T) == 1, "No valid members");

View File

@ -18,12 +18,12 @@ void testAmbiguousNoSuggestions()
namespace MultipleCorrectionsButNotAmbiguous
{
int PrefixType_Name(int value); // expected-note {{'PrefixType_Name' declared here}}
int PrefixType_Name(int value);
int PrefixType_MIN();
int PrefixType_MAX();
};
int testMultipleCorrectionsButNotAmbiguous() {
int val = MultipleCorrectionsButNotAmbiguous::PrefixType_Enum(0); // expected-error {{no member named 'PrefixType_Enum' in namespace 'MultipleCorrectionsButNotAmbiguous'; did you mean 'PrefixType_Name'?}}
int val = MultipleCorrectionsButNotAmbiguous::PrefixType_Enum(0); // expected-error {{no member named 'PrefixType_Enum' in namespace 'MultipleCorrectionsButNotAmbiguous'}}
return val;
}

View File

@ -2,16 +2,15 @@
// PR50797
struct a {
int xxx; // expected-note {{'xxx' declared here}}
int xxx;
};
int g_107;
int g_108;
int g_109;
struct a g_999; // expected-note 4{{'g_999' declared here}}
struct a g_999;
void b(void) { (g_910.xxx = g_910.xxx); } //expected-error 2{{use of undeclared identifier 'g_910'; did you mean 'g_999'}}
void b(void) { (g_910.xxx = g_910.xxx); } //expected-error 2{{use of undeclared identifier 'g_910'}}
void c(void) { (g_910.xxx = g_910.xxx1); } //expected-error 2{{use of undeclared identifier 'g_910'; did you mean 'g_999'}} \
expected-error {{no member named 'xxx1' in 'struct a'; did you mean 'xxx'}}
void c(void) { (g_910.xxx = g_910.xxx1); } //expected-error 2{{use of undeclared identifier 'g_910'}}

View File

@ -8,10 +8,12 @@ struct rdar38642201 {
void rdar38642201_callee(int x, int y);
void rdar38642201_caller() {
struct rdar38642201 structVar;
struct rdar38642201 structVar; //expected-note 2{{'structVar' declared here}}
rdar38642201_callee(
structVar1.fieldName1.member1, //expected-error{{use of undeclared identifier 'structVar1'}}
structVar2.fieldName2.member2); //expected-error{{use of undeclared identifier 'structVar2'}}
structVar1.fieldName1.member1, //expected-error{{use of undeclared identifier 'structVar1'}} \
expected-error{{no member named 'fieldName1' in 'rdar38642201'}}
structVar2.fieldName2.member2); //expected-error{{use of undeclared identifier 'structVar2'}} \
expected-error{{no member named 'fieldName2' in 'rdar38642201'}}
}
// Similar reproducer.
@ -20,7 +22,7 @@ public:
int minut() const = delete;
int hour() const = delete;
int longit() const; //expected-note{{'longit' declared here}}
int longit() const;
int latit() const;
};
@ -35,6 +37,6 @@ int Foo(const B &b) {
}
int Bar(const B &b) {
return b.depar().longitude() + //expected-error{{no member named 'longitude' in 'A'; did you mean 'longit'?}}
return b.depar().longitude() + //expected-error{{no member named 'longitude' in 'A'}}
b.depar().latitude(); //expected-error{{no member named 'latitude' in 'A'}}
}

View File

@ -8,13 +8,13 @@
class DeepClass
{
public:
void trigger() const; // expected-note {{'trigger' declared here}}
void trigger() const;
};
class Y
{
public:
const DeepClass& getX() const { return m_deepInstance; } // expected-note {{'getX' declared here}}
const DeepClass& getX() const { return m_deepInstance; }
private:
DeepClass m_deepInstance;
int m_n;
@ -23,7 +23,7 @@ private:
class Z
{
public:
const Y& getY0() const { return m_y0; } // expected-note {{'getY0' declared here}}
const Y& getY0() const { return m_y0; }
const Y& getActiveY() const { return m_y0; }
private:
@ -35,9 +35,9 @@ Z z_obj;
void testMultipleCorrections()
{
z_obj.getY2(). // expected-error {{no member named 'getY2' in 'Z'; did you mean 'getY0'}}
getM(). // expected-error {{no member named 'getM' in 'Y'; did you mean 'getX'}}
triggee(); // expected-error {{no member named 'triggee' in 'DeepClass'; did you mean 'trigger'}}
z_obj.getY2(). // expected-error {{no member named 'getY2' in 'Z'}}
getM().
triggee();
}
void testNoCorrections()
@ -53,19 +53,19 @@ struct A {
C get_me_a_C();
};
struct B {
D get_me_a_D(); // expected-note {{'get_me_a_D' declared here}}
D get_me_a_D();
};
class Scope {
public:
A make_an_A();
B make_a_B(); // expected-note {{'make_a_B' declared here}}
B make_a_B();
};
Scope scope_obj;
int testDiscardedCorrections() {
return scope_obj.make_an_E(). // expected-error {{no member named 'make_an_E' in 'Scope'; did you mean 'make_a_B'}}
get_me_a_Z().value; // expected-error {{no member named 'get_me_a_Z' in 'B'; did you mean 'get_me_a_D'}}
return scope_obj.make_an_E(). // expected-error {{no member named 'make_an_E' in 'Scope'}}
get_me_a_Z().value;
}
class AmbiguousHelper {
@ -120,13 +120,13 @@ int testDeepAmbiguity() {
}
struct Dog {
int age; //expected-note{{'age' declared here}}
int size; //expected-note{{'size' declared here}}
int age;
int size;
};
int from_dog_years(int DogYears, int DogSize);
int get_dog_years() {
struct Dog doggo;
return from_dog_years(doggo.agee, //expected-error{{no member named 'agee' in 'Dog'; did you mean 'age'}}
doggo.sizee); //expected-error{{no member named 'sizee' in 'Dog'; did you mean 'size'}}
return from_dog_years(doggo.agee, //expected-error{{no member named 'agee' in 'Dog'}}
doggo.sizee); //expected-error{{no member named 'sizee' in 'Dog'}}
}

View File

@ -50,10 +50,12 @@ void fn1(void) {
cabs(errij); // expected-error {{use of undeclared identifier 'errij'}}
}
extern long afunction(int);
extern long afunction(int); // expected-note {{'afunction' declared here}} \
expected-note {{passing argument to parameter here}}
void fn2(void) {
f(THIS_IS_AN_ERROR, // expected-error {{use of undeclared identifier 'THIS_IS_AN_ERROR'}}
afunction(afunction_)); // expected-error {{use of undeclared identifier 'afunction_'}}
afunction(afunction_)); // expected-error {{use of undeclared identifier 'afunction_'}} \
expected-error {{incompatible pointer to integer conversion passing 'long (int)' to parameter of type 'int'}}
}
int d = X ? d : L; // expected-error 2 {{use of undeclared identifier}}
@ -94,22 +96,24 @@ struct rdar38642201 {
void rdar38642201_callee(int x, int y);
void rdar38642201_caller(void) {
struct rdar38642201 structVar;
struct rdar38642201 structVar; // expected-note 2{{'structVar' declared here}}
rdar38642201_callee(
structVar1.fieldName1.member1, //expected-error{{use of undeclared identifier 'structVar1'}}
structVar2.fieldName2.member2); //expected-error{{use of undeclared identifier 'structVar2'}}
structVar1.fieldName1.member1, //expected-error{{use of undeclared identifier 'structVar1'}} \
expected-error{{no member named 'fieldName1' in 'struct rdar38642201'}}
structVar2.fieldName2.member2); //expected-error{{use of undeclared identifier 'structVar2'}} \
expected-error{{no member named 'fieldName2' in 'struct rdar38642201'}}
}
void PR40286_g(int x, int y);
void PR40286_h(int x, int y, int z);
void PR40286_1(int the_value) {
PR40286_g(the_walue); // expected-error {{use of undeclared identifier 'the_walue'}}
void PR40286_1(int the_value) { // expected-note {{'the_value' declared here}}
PR40286_g(the_walue, 0); // expected-error {{use of undeclared identifier 'the_walue'}}
}
void PR40286_2(int the_value) {
PR40286_h(the_value, the_walue); // expected-error {{use of undeclared identifier 'the_walue'}}
void PR40286_2(int the_value) { // expected-note {{'the_value' declared here}}
PR40286_h(the_value, the_walue, 0); // expected-error {{use of undeclared identifier 'the_walue'}}
}
void PR40286_3(int the_value) {
PR40286_h(the_walue); // expected-error {{use of undeclared identifier 'the_walue'}}
void PR40286_3(int the_value) { // expected-note {{'the_value' declared here}}
PR40286_h(the_walue, 0, 0); // expected-error {{use of undeclared identifier 'the_walue'}}
}
void PR40286_4(int the_value) { // expected-note {{'the_value' declared here}}
PR40286_h(the_value, the_value, the_walue); // expected-error {{use of undeclared identifier 'the_walue'; did you mean 'the_value'?}}

View File

@ -47,23 +47,22 @@ class wrapped_ptr {
public:
wrapped_ptr(T* ptr) : ptr_(ptr) {}
T* operator->() { return ptr_; }
void Check(); // expected-note {{'Check' declared here}}
void Check();
private:
T *ptr_;
};
class Worker {
public:
void DoSomething(); // expected-note {{'DoSomething' declared here}}
void DoSomething();
void Chuck();
};
void test() {
wrapped_ptr<Worker> worker(new Worker);
worker.DoSomething(); // expected-error {{no member named 'DoSomething' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'; did you mean to use '->' instead of '.'?}}
worker.DoSamething(); // expected-error {{no member named 'DoSamething' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'; did you mean to use '->' instead of '.'?}} \
// expected-error {{no member named 'DoSamething' in 'arrow_suggest::Worker'; did you mean 'DoSomething'?}}
worker.Chuck(); // expected-error {{no member named 'Chuck' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'; did you mean 'Check'?}}
worker.DoSamething(); // expected-error {{no member named 'DoSamething' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'}}
worker.Chuck(); // expected-error {{no member named 'Chuck' in 'arrow_suggest::wrapped_ptr<arrow_suggest::Worker>'}}
}
} // namespace arrow_suggest

View File

@ -1888,10 +1888,11 @@ namespace PR15884 {
}
namespace AfterError {
constexpr int error() {
constexpr int error() { // pre-cxx23-error {{no return statement in constexpr function}}
return foobar; // expected-error {{undeclared identifier}}
}
constexpr int k = error(); // expected-error {{constexpr variable 'k' must be initialized by a constant expression}}
} // cxx23-note {{control reached end of constexpr function}}
constexpr int k = error(); // cxx23-error {{constexpr variable 'k' must be initialized by a constant expression}} \
cxx23-note {{in call to 'error()'}}
}
namespace std {

View File

@ -458,7 +458,7 @@ namespace PR18234 {
#endif
} a;
A::S s = a; // expected-error {{no viable conversion from 'struct A' to 'A::S'}}
A::E e = a;
A::E e = a; // expected-note {{'e' declared here}}
bool k1 = e == A::e; // expected-error {{no member named 'e'}}
bool k2 = e.n == 0;
}

View File

@ -8,19 +8,16 @@
// RUN: not %clang_cc1 -std=c++20 -fsyntax-only %s -fcxx-exceptions -fexceptions -Wunused-result 2>&1 | FileCheck %s
void no_coroutine_traits_bad_arg_await() {
co_await a; // expected-error {{include <coroutine>}}
// expected-error@-1 {{use of undeclared identifier 'a'}}
co_await a; // expected-error {{use of undeclared identifier 'a'}}
}
void no_coroutine_traits_bad_arg_yield() {
co_yield a; // expected-error {{include <coroutine>}}
// expected-error@-1 {{use of undeclared identifier 'a'}}
co_yield a; // expected-error {{use of undeclared identifier 'a'}}
}
void no_coroutine_traits_bad_arg_return() {
co_return a; // expected-error {{include <coroutine>}}
// expected-error@-1 {{use of undeclared identifier 'a'}}
co_return a; // expected-error {{use of undeclared identifier 'a'}}
}
void no_coroutine_traits() {
@ -208,8 +205,7 @@ void mixed_yield() {
void mixed_yield_invalid() {
co_yield blah; // expected-error {{use of undeclared identifier}}
// expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
return; // expected-error {{return statement not allowed in coroutine}}
return;
}
void mixed_yield_return_first(bool b) {
@ -231,8 +227,7 @@ void mixed_return_for_range(bool b, T t) {
template <class T>
void mixed_yield_template(T) {
co_yield blah; // expected-error {{use of undeclared identifier}}
// expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
return; // expected-error {{return statement not allowed in coroutine}}
return;
}
template <class T>
@ -314,10 +309,9 @@ template void mixed_coreturn_template(void_tag, bool, int); // expected-note {{r
template <class T>
void mixed_coreturn_template2(bool b, T) {
if (b)
co_return v; // expected-note {{use of 'co_return'}}
// expected-error@-1 {{use of undeclared identifier 'v'}}
co_return v; // expected-error {{use of undeclared identifier 'v'}}
else
return; // expected-error {{not allowed in coroutine}}
return;
}
struct promise_handle;

View File

@ -0,0 +1,67 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
namespace GH138850 {
void test() {
int tmp = add(int, 0, 0); // expected-error {{expected '(' for function-style cast or type construction}} \
expected-note {{previous definition is here}}
uint tmp = add(uint, 1, 1); // expected-error {{use of undeclared identifier 'uint'; did you mean 'int'?}} \
expected-error {{redefinition of 'tmp'}} \
expected-error {{use of undeclared identifier 'uint'}}
call(void, f, (int)tmp); // expected-error {{expected '(' for function-style cast or type construction}} \
expected-error {{use of undeclared identifier 'f'}}
}
}
namespace GH107840 {
struct tm {}; // expected-note {{'tm' declared here}}
auto getCache = [&] { // expected-error {{non-local lambda expression cannot have a capture-default}}
::foo([=] { // expected-error {{no member named 'foo' in the global namespace}}
tms time; // expected-error {{unknown type name 'tms'; did you mean 'tm'?}}
(void)time;
});
};
}
namespace GH59391 {
template <typename b> class c {
c(b);
b e;
void f() {
for (auto core : a::c(cores)) { // expected-error {{use of undeclared identifier 'cores'}} \
expected-error {{use of undeclared identifier 'a'}}
}
}
};
}
namespace GH45915 {
short g_volatile_ushort; // expected-note {{'g_volatile_ushort' declared here}}
namespace a {
int b = l_volatile_uwchar.a ::c ::~d<>; // expected-error {{use of undeclared identifier 'l_volatile_uwchar'}} \
expected-error {{no member named 'd' in namespace 'GH45915::a'}}
}
}
namespace GH45891 {
int a = b.c < enum , > :: template ~d < > [ e; // expected-error {{use of undeclared identifier 'b'}} \
expected-error {{expected identifier or '{'}} \
expected-error {{expected ';' after top level declarator}}
}
namespace GH32903 {
void
B(
char cat_dog_3, char cat_dog_2, char cat_dog_1, char cat_dog_0, char pigeon_dog_3, char pigeon_dog_2,
char pigeon_dog_1, char pigeon_dog_0, short &elefant15_lion, short &elefant14_lion, short &elefant13_lion, // expected-note 3 {{declared here}}
short &elefant12_lion, short &elefant11_lion, short &elefant10_lion, short &elefant9_lion, short &elefant8_lion, // expected-note 5 {{declared here}}
short &elefant7_lion, short &elefant6_lion, short &elefant5_lion, short &elefant4_lion, short &elefant3_lion, // expected-note 2 {{declared here}}
short &elefant2_lion, short &elefant1_lion, short &elefant0_lion, char& no_animal)
{
A( // FIXME: it's surprising that we don't issue a "use of undeclared identifier" diagnostic for the call itself.
elefant_15_lion, elefant_14_lion, elefant_13_lion, elefant_12_lion, elefant_11_lion, elefant_10_lion, elefant_9_lion, // expected-error 7 {{use of undeclared identifier}}
elefant_8_lion, elefant_7_lion, elefant_6_lion, elefant_5_lion, elefant_4_lion, elefant_3_lion, elefant_2_lion, // expected-error 7 {{use of undeclared identifier}}
elefant_1_lion, elefant_0_lion, no_animal, other_mammal); // expected-error 3 {{use of undeclared identifier}}
}
}

View File

@ -121,7 +121,8 @@ void for_range() {
}
int error_recovery() {
auto [foobar]; // expected-error {{requires an initializer}}
auto [foobar]; // expected-error {{requires an initializer}} \
expected-note {{'foobar' declared here}}
return foobar_; // expected-error {{undeclared identifier 'foobar_'}}
}

View File

@ -0,0 +1,19 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
#include "Inputs/std-coroutine.h"
namespace GH58172 {
template<typename Fn>
int f2(int, Fn&&)
{
return 0;
}
int f1()
{
return f2(v1, []() -> task<int> { // expected-error {{no template named 'task'}} \
expected-error {{use of undeclared identifier 'v1'}}
co_return v2; // expected-error {{use of undeclared identifier 'v2'}}
});
}
}

View File

@ -61,7 +61,7 @@ struct A : X<int> { // expected-error {{no template named 'X'}}
// Similarly for treating overload sets of functions as template names.
struct g<int> {}; // expected-error {{'g' refers to a function template}}
g<int>::Y xy; // expected-error {{no template named 'g'}} FIXME lies
void xf(g<int> x); // expected-error {{variable has incomplete type 'void'}} expected-error 1+{{}} expected-note {{}}
void xf(g<int> x); // expected-error {{variable has incomplete type 'void'}} expected-error 1+{{}}
struct B : g<int> { // expected-error {{expected class name}}
B() : g<int>() {} // expected-error {{expected class member or base class name}}
};

View File

@ -553,14 +553,11 @@ namespace crash_on_invalid_base_dtor {
struct Test {
virtual ~Test();
};
struct Baz : public Test { // expected-warning {{non-virtual destructor}}
struct Baz : public Test {
Baz() {}
~Baz() = defaul; // expected-error {{undeclared identifier 'defaul'}} \
// expected-error {{initializer on function}} \
// expected-note {{overridden virtual function is here}}
~Baz() = defaul; // expected-error {{undeclared identifier 'defaul'}}
};
struct Foo : public Baz { // expected-error {{cannot override a non-deleted function}} \
// expected-note {{destructor of 'Foo' is implicitly deleted}}
struct Foo : public Baz {
Foo() {}
};
}
@ -579,11 +576,9 @@ static_assert(!__is_trivially_constructible(Foo, Foo &&), "");
namespace GH97230 {
struct X {
~X() = defaul; // expected-error {{initializer on function does not look like a pure-specifier}} \
// expected-error {{use of undeclared identifier 'defaul'}}
~X() = defaul; // expected-error {{use of undeclared identifier 'defaul'}}
};
struct Y : X {} y1{ }; // expected-error {{call to implicitly-deleted default constructor of 'struct Y'}} \
// expected-note {{default constructor of 'Y' is implicitly deleted because base class 'X' has no destructor}}
struct Y : X {} y1{ };
}
namespace GH121706 {

View File

@ -2,12 +2,16 @@
namespace GH61885 {
void similar() { // expected-note {{'similar' declared here}}
if constexpr (similer<>) {} // expected-error {{use of undeclared identifier 'similer'; did you mean 'similar'?}}
if constexpr (similer<>) {} // expected-error {{use of undeclared identifier 'similer'; did you mean 'similar'?}} \
expected-warning {{address of function 'similar<>' will always evaluate to 'true'}} \
expected-note {{prefix with the address-of operator to silence this warning}}
}
void a() { if constexpr (__adl_swap<>) {}} // expected-error{{use of undeclared identifier '__adl_swap'; did you mean '__sync_swap'?}}
void a() { if constexpr (__adl_swap<>) {}} // expected-error{{use of undeclared identifier '__adl_swap'}}
int AA() { return true;} // expected-note {{'AA' declared here}}
void b() { if constexpr (AAA<>) {}} // expected-error {{use of undeclared identifier 'AAA'; did you mean 'AA'?}}
void b() { if constexpr (AAA<>) {}} // expected-error {{use of undeclared identifier 'AAA'; did you mean 'AA'?}} \
expected-warning {{address of function 'AA<>' will always evaluate to 'true'}} \
expected-note {{prefix with the address-of operator to silence this warning}}
}

View File

@ -96,11 +96,11 @@ namespace test5 {
namespace PR7508 {
struct A {
struct CleanupScope {};
void PopCleanupBlock(); // expected-note{{'PopCleanupBlock' declared here}}
void PopCleanupBlock();
};
void foo(A &a) {
a.PopCleanupScope(); // expected-error{{no member named 'PopCleanupScope' in 'PR7508::A'; did you mean 'PopCleanupBlock'?}}
a.PopCleanupScope(); // expected-error{{no member named 'PopCleanupScope' in 'PR7508::A'}}
}
}
@ -189,7 +189,7 @@ namespace PR15045 {
}
struct bar {
void func(); // expected-note {{'func' declared here}}
void func();
};
struct foo {
@ -207,7 +207,7 @@ namespace PR15045 {
// Show that recovery has happened by also triggering typo correction
e->Func(); // expected-error {{member reference type 'bar' is not a pointer; did you mean to use '.'?}} \
// expected-error {{no member named 'Func' in 'PR15045::bar'; did you mean 'func'?}}
// expected-error {{no member named 'Func' in 'PR15045::bar'}}
// Make sure a fixit isn't given in the case that the '->' isn't actually
// the problem (the problem is with the return value of an operator->).

View File

@ -409,7 +409,8 @@ T1<C2::N1> var_1a;
T1<C2:N1> var_1b; // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
template<int N> int F() {}
int (*X1)() = (B1::B2 ? F<1> : F<2>);
int (*X2)() = (B1:B2 ? F<1> : F<2>); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}}
int (*X2)() = (B1:B2 ? F<1> : F<2>); // expected-error{{unexpected ':' in nested name specifier; did you mean '::'?}} \
expected-note{{'PR18587::X2' declared here}}
// Bit fields + templates
struct S7a {
@ -445,7 +446,8 @@ namespace PR16951 {
int x4 = enumerator_2::ENUMERATOR_2; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
int x5 = enumerator_2::X2; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
// expected-error{{no member named 'X2' in 'PR16951::enumerator_2'}}
// expected-error{{no member named 'X2' in 'PR16951::enumerator_2'}} \
// expected-error{{cannot initialize a variable of type 'int' with an lvalue of type 'int (*)()'}}
}

View File

@ -1,29 +0,0 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
// Don't crash (PR13394).
namespace stretch_v1 {
struct closure_t {
const stretch_v1::ops_t* d_methods; // expected-error {{no type named 'ops_t' in namespace 'stretch_v1'}}
};
}
namespace gatekeeper_v1 {
namespace gatekeeper_factory_v1 {
struct closure_t { // expected-note {{'closure_t' declared here}} expected-note {{'gatekeeper_factory_v1::closure_t' declared here}}
gatekeeper_v1::closure_t* create(); // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1'; did you mean simply 'closure_t'?}}
};
}
// FIXME: Typo correction should remove the 'gatekeeper_v1::' name specifier
gatekeeper_v1::closure_t *x; // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1'; did you mean 'gatekeeper_factory_v1::closure_t'}}
}
namespace Foo {
struct Base {
void Bar() {} // expected-note{{'Bar' declared here}}
};
}
struct Derived : public Foo::Base {
void test() {
Foo::Bar(); // expected-error{{no member named 'Bar' in namespace 'Foo'; did you mean simply 'Bar'?}}
}
};

View File

@ -130,5 +130,5 @@ void cxx_unresolved_expr() {
// CXXUnresolvedConstructExpr, and the missing ')' gives it an invalid source
// location for its rparen. Check that emitting a diag on the range of the
// expr doesn't assert.
return int(undeclared, 4; // expected-error {{expected ')'}} expected-note{{to match this '('}} expected-error {{use of undeclared identifier 'undeclared'}}
return int(undeclared, 4; // expected-error {{use of undeclared identifier 'undeclared'}}
}

View File

@ -4,10 +4,10 @@ auto check1() {
return s; // expected-error {{use of undeclared identifier 's'}}
}
int test = 11; // expected-note 2 {{'test' declared here}}
int test = 11; // expected-note 3 {{'test' declared here}}
auto check2() {
return "s";
return tes; // expected-error {{use of undeclared identifier 'tes'; did you mean 'test'?}}
return tes; // expected-error {{use of undeclared identifier 'tes'}}
// expected-error@-1 {{deduced as 'int' here but deduced as 'const char *' in earlier}}
}
@ -16,9 +16,8 @@ template <class A> struct is_same<A,A> { static constexpr bool value = true; };
auto L1 = [] { return s; }; // expected-error {{use of undeclared identifier 's'}}
using T1 = decltype(L1());
// FIXME: Suppress the 'undeclared identifier T1' diagnostic, the UsingDecl T1 is discarded because of an invalid L1().
static_assert(is_same<T1, void>::value, "Return statement should be discarded"); // expected-error {{use of undeclared identifier 'T1'}}
auto L2 = [] { return tes; }; // expected-error {{use of undeclared identifier 'tes'; did you mean 'test'?}}
static_assert(is_same<T1, void>::value, "Return statement should be discarded");
auto L2 = [] { return tes; }; // expected-error {{use of undeclared identifier 'tes'}}
using T2 = decltype(L2());
static_assert(is_same<T2, int>::value, "Return statement was corrected");
@ -32,13 +31,13 @@ FooRecord::NestedNamespace::type x; // expected-error {{no member named 'NestedN
void cast_expr(int g) { +int(n)(g); } // expected-error {{undeclared identifier 'n'}}
void bind() { for (const auto& [test,_] : _test_) { }; } // expected-error {{undeclared identifier '_test_'}}
void bind() { for (const auto& [test,_] : _test_) { }; } // expected-error {{undeclared identifier '_test_'}} \
expected-error {{invalid range expression of type 'int'; no viable 'begin' function available}}
namespace NoCrash {
class S {
void Function(int a) {
unknown1(unknown2, Function, unknown3); // expected-error 2{{use of undeclared identifier}} \
expected-error {{reference to non-static member function must be called}}
unknown1(unknown2, Function, unknown3); // expected-error 2{{use of undeclared identifier}}
}
};
}
@ -46,8 +45,6 @@ class S {
namespace NoCrashOnCheckArgAlignment {
template <typename a> void b(a &);
void test() {
for (auto file_data :b(files_db_data)); // expected-error {{use of undeclared identifier 'files_db_data'; did you mean 'file_data'?}} \
// expected-note {{'file_data' declared here}} \
// expected-error {{cannot use type 'void' as a range}}
for (auto file_data :b(files_db_data)); // expected-error {{use of undeclared identifier 'files_db_data'}}
}
}

Some files were not shown because too many files have changed in this diff Show More