diff options
| -rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 32 | ||||
| -rw-r--r-- | clang/test/SemaCXX/typo-correction.cpp | 12 |
2 files changed, 37 insertions, 7 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index bcb624be899..a4282e29462 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -1529,6 +1529,26 @@ static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef, DIE->usesGNUSyntax(), DIE->getInit()); } +namespace { + +// Callback to only accept typo corrections that are for field members of +// the given struct or union. +class FieldInitializerValidatorCCC : public CorrectionCandidateCallback { + public: + explicit FieldInitializerValidatorCCC(RecordDecl *RD) + : Record(RD) {} + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>(); + return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record); + } + + private: + RecordDecl *Record; +}; + +} + /// @brief Check the well-formedness of a C99 designated initializer. /// /// Determines whether the designated initializer @p DIE, which @@ -1687,19 +1707,17 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, if (Lookup.first == Lookup.second) { // Name lookup didn't find anything. Determine whether this // was a typo for another field name. - LookupResult R(SemaRef, FieldName, D->getFieldLoc(), - Sema::LookupMemberName); + FieldInitializerValidatorCCC Validator(RT->getDecl()); TypoCorrection Corrected = SemaRef.CorrectTypo( DeclarationNameInfo(FieldName, D->getFieldLoc()), - Sema::LookupMemberName, /*Scope=*/NULL, /*SS=*/NULL, - RT->getDecl(), false, Sema::CTC_NoKeywords); - if ((ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>()) && - ReplacementField->getDeclContext()->getRedeclContext() - ->Equals(RT->getDecl())) { + Sema::LookupMemberName, /*Scope=*/0, /*SS=*/0, &Validator, + RT->getDecl()); + if (Corrected) { std::string CorrectedStr( Corrected.getAsString(SemaRef.getLangOptions())); std::string CorrectedQuotedStr( Corrected.getQuoted(SemaRef.getLangOptions())); + ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>(); SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown_suggest) << FieldName << CurrentObjectType << CorrectedQuotedStr diff --git a/clang/test/SemaCXX/typo-correction.cpp b/clang/test/SemaCXX/typo-correction.cpp index c3e8480b293..9187c1bf129 100644 --- a/clang/test/SemaCXX/typo-correction.cpp +++ b/clang/test/SemaCXX/typo-correction.cpp @@ -47,3 +47,15 @@ class some_name {}; // expected-note {{'some_name' declared here}} somename Foo; // expected-error {{unknown type name 'somename'; did you mean 'some_name'?}} namespace SomeName {} // expected-note {{namespace 'SomeName' defined here}} using namespace somename; // expected-error {{no namespace named 'somename'; did you mean 'SomeName'?}} + + +// Without the callback object, CorrectTypo would choose "field1" as the +// correction for "fielda" as it is closer than "FieldA", but that correction +// would be later discarded by the caller and no suggestion would be given. +struct st { + struct { + int field1; + }; + double FieldA; // expected-note{{'FieldA' declared here}} +}; +st var = { .fielda = 0.0 }; // expected-error{{field designator 'fielda' does not refer to any field in type 'st'; did you mean 'FieldA'?}} |

