Properly correct initializer expressions based on whether they would be valid.

llvm-svn: 222550
This commit is contained in:
Kaelyn Takata 2014-11-21 18:48:00 +00:00
parent 5ca2ecd2b2
commit 4c3ffc4fef
2 changed files with 51 additions and 0 deletions

View File

@ -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()) {

View File

@ -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'{{$}}}}
}
}