forked from OSchip/llvm-project
Properly correct initializer expressions based on whether they would be valid.
llvm-svn: 222550
This commit is contained in:
parent
5ca2ecd2b2
commit
4c3ffc4fef
|
@ -8799,6 +8799,23 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
|
|||
Args = MultiExprArg(CXXDirectInit->getExprs(),
|
||||
CXXDirectInit->getNumExprs());
|
||||
|
||||
// Try to correct any TypoExprs if there might be some in the initialization
|
||||
// arguments (TypoExprs are marked as type-dependent).
|
||||
// TODO: Handle typo correction when there's more than one argument?
|
||||
if (Args.size() == 1 && Expr::hasAnyTypeDependentArguments(Args)) {
|
||||
ExprResult Res =
|
||||
CorrectDelayedTyposInExpr(Args[0], [this, Entity, Kind](Expr *E) {
|
||||
InitializationSequence Init(*this, Entity, Kind, MultiExprArg(E));
|
||||
return Init.Failed() ? ExprError() : E;
|
||||
});
|
||||
if (Res.isInvalid()) {
|
||||
VDecl->setInvalidDecl();
|
||||
return;
|
||||
}
|
||||
if (Res.get() != Args[0])
|
||||
Args[0] = Res.get();
|
||||
}
|
||||
|
||||
InitializationSequence InitSeq(*this, Entity, Kind, Args);
|
||||
ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT);
|
||||
if (Result.isInvalid()) {
|
||||
|
|
|
@ -59,3 +59,37 @@ void testExprFilter(Item *i) {
|
|||
Item *j;
|
||||
j = i->Next(); // expected-error {{no member named 'Next' in 'Item'; did you mean 'next'?}}
|
||||
}
|
||||
|
||||
// Test that initializer expressions are handled correctly and that the type
|
||||
// being initialized is taken into account when choosing a correction.
|
||||
namespace initializerCorrections {
|
||||
struct Node {
|
||||
string text() const;
|
||||
// Node* Next() is not implemented yet
|
||||
};
|
||||
void f(Node *node) {
|
||||
// text is only an edit distance of 1 from Next, but would trigger type
|
||||
// conversion errors if used in this initialization expression.
|
||||
Node *next = node->Next(); // expected-error-re {{no member named 'Next' in 'initializerCorrections::Node'{{$}}}}
|
||||
}
|
||||
|
||||
struct LinkedNode {
|
||||
LinkedNode* next(); // expected-note {{'next' declared here}}
|
||||
string text() const;
|
||||
};
|
||||
void f(LinkedNode *node) {
|
||||
// text and next are equidistant from Next, but only one results in a valid
|
||||
// initialization expression.
|
||||
LinkedNode *next = node->Next(); // expected-error {{no member named 'Next' in 'initializerCorrections::LinkedNode'; did you mean 'next'?}}
|
||||
}
|
||||
|
||||
struct NestedNode {
|
||||
NestedNode* Nest();
|
||||
NestedNode* next();
|
||||
string text() const;
|
||||
};
|
||||
void f(NestedNode *node) {
|
||||
// There are two equidistant, usable corrections for Next: next and Nest
|
||||
NestedNode *next = node->Next(); // expected-error-re {{no member named 'Next' in 'initializerCorrections::NestedNode'{{$}}}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue