[cfe-commits] r141621 - in /cfe/trunk: include/clang/Parse/Parser.h include/clang/Sema/Sema.h lib/Parse/ParseDecl.cpp lib/Parse/Parser.cpp lib/Sema/SemaDecl.cpp test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp test/SemaCXX/typo-corre

Eli Friedman eli.friedman at gmail.com
Mon Oct 10 18:22:02 PDT 2011


On Mon, Oct 10, 2011 at 6:02 PM, Kaelyn Uhrain <rikka at google.com> wrote:
> Author: rikka
> Date: Mon Oct 10 20:02:41 2011
> New Revision: 141621
>
> URL: http://llvm.org/viewvc/llvm-project?rev=141621&view=rev
> Log:
> Add typo correction for type names.
>
> The main motivation was to do typo correction in C++ "new" statements,
> though picking it up in other places where type names are expected was
> pretty much a freebie.
>
> Added:
>    cfe/trunk/test/SemaCXX/typo-correction.cpp
> Modified:
>    cfe/trunk/include/clang/Parse/Parser.h
>    cfe/trunk/include/clang/Sema/Sema.h
>    cfe/trunk/lib/Parse/ParseDecl.cpp
>    cfe/trunk/lib/Parse/Parser.cpp
>    cfe/trunk/lib/Sema/SemaDecl.cpp
>    cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp
>
> Modified: cfe/trunk/include/clang/Parse/Parser.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=141621&r1=141620&r2=141621&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Parse/Parser.h (original)
> +++ cfe/trunk/include/clang/Parse/Parser.h Mon Oct 10 20:02:41 2011
> @@ -436,7 +436,10 @@
>       Tok.setAnnotationValue(ER.get());
>   }
>
> -  bool TryAnnotateTypeOrScopeToken(bool EnteringContext = false);
> +  // If NeedType is true, then TryAnnotateTypeOrScopeToken will try harder to
> +  // find a type name by attempting typo correction.
> +  bool TryAnnotateTypeOrScopeToken(bool EnteringContext = false,
> +                                   bool NeedType = false);
>   bool TryAnnotateCXXScopeToken(bool EnteringContext = false);
>
>   /// TryAltiVecToken - Check for context-sensitive AltiVec identifier tokens,
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=141621&r1=141620&r2=141621&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Mon Oct 10 20:02:41 2011
> @@ -873,7 +873,8 @@
>                          bool isClassName = false,
>                          bool HasTrailingDot = false,
>                          ParsedType ObjectType = ParsedType(),
> -                         bool WantNontrivialTypeSourceInfo = false);
> +                         bool WantNontrivialTypeSourceInfo = false,
> +                         IdentifierInfo **CorrectedII = 0);
>   TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
>   bool isMicrosoftMissingTypename(const CXXScopeSpec *SS);
>   bool DiagnoseUnknownTypeName(const IdentifierInfo &II,
>
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=141621&r1=141620&r2=141621&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Oct 10 20:02:41 2011
> @@ -2303,7 +2303,8 @@
>   case tok::kw_typename:  // typename foo::bar
>     // Annotate typenames and C++ scope specifiers.  If we get one, just
>     // recurse to handle whatever we get.
> -    if (TryAnnotateTypeOrScopeToken())
> +    if (TryAnnotateTypeOrScopeToken(/*EnteringContext=*/false,
> +                                    /*NeedType=*/true))
>       return true;
>     if (Tok.is(tok::identifier))
>       return false;
> @@ -2316,7 +2317,8 @@
>
>     // Annotate typenames and C++ scope specifiers.  If we get one, just
>     // recurse to handle whatever we get.
> -    if (TryAnnotateTypeOrScopeToken())
> +    if (TryAnnotateTypeOrScopeToken(/*EnteringContext=*/false,
> +                                    /*NeedType=*/true))
>       return true;
>     return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
>                                       TemplateInfo, SuppressDeclarations);
>
> Modified: cfe/trunk/lib/Parse/Parser.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=141621&r1=141620&r2=141621&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/Parser.cpp (original)
> +++ cfe/trunk/lib/Parse/Parser.cpp Mon Oct 10 20:02:41 2011
> @@ -1204,7 +1204,7 @@
>  ///
>  /// Note that this routine emits an error if you call it with ::new or ::delete
>  /// as the current tokens, so only call it in contexts where these are invalid.
> -bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
> +bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) {
>   assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)
>           || Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope)) &&
>          "Cannot be a type or scope token!");
> @@ -1278,13 +1278,18 @@
>       return true;
>
>   if (Tok.is(tok::identifier)) {
> +    IdentifierInfo *CorrectedII = 0;
>     // Determine whether the identifier is a type name.
>     if (ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(),
>                                             Tok.getLocation(), getCurScope(),
>                                             &SS, false,
>                                             NextToken().is(tok::period),
>                                             ParsedType(),
> -                                            /*NonTrivialTypeSourceInfo*/true)) {
> +                                            /*NonTrivialTypeSourceInfo*/true,
> +                                            NeedType ? &CorrectedII : NULL)) {
> +      // A FixIt was applied as a result of typo correction
> +      if (CorrectedII)
> +        Tok.setIdentifierInfo(CorrectedII);
>       // This is a typename. Replace the current token in-place with an
>       // annotation type token.
>       Tok.setKind(tok::annot_typename);
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=141621&r1=141620&r2=141621&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Oct 10 20:02:41 2011
> @@ -71,7 +71,8 @@
>                              Scope *S, CXXScopeSpec *SS,
>                              bool isClassName, bool HasTrailingDot,
>                              ParsedType ObjectTypePtr,
> -                             bool WantNontrivialTypeSourceInfo) {
> +                             bool WantNontrivialTypeSourceInfo,
> +                             IdentifierInfo **CorrectedII) {
>   // Determine where we will perform name lookup.
>   DeclContext *LookupCtx = 0;
>   if (ObjectTypePtr) {
> @@ -146,6 +147,51 @@
>   switch (Result.getResultKind()) {
>   case LookupResult::NotFound:
>   case LookupResult::NotFoundInCurrentInstantiation:
> +    if (CorrectedII) {
> +      TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(),
> +                                              Kind, S, SS, 0, false,
> +                                              Sema::CTC_Type);
> +      IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo();
> +      TemplateTy Template;
> +      bool MemberOfUnknownSpecialization;
> +      UnqualifiedId TemplateName;
> +      TemplateName.setIdentifier(NewII, NameLoc);
> +      NestedNameSpecifier *NNS = Correction.getCorrectionSpecifier();
> +      CXXScopeSpec NewSS, *NewSSPtr = SS;
> +      if (SS && NNS) {
> +        NewSS.MakeTrivial(Context, NNS, SourceRange(NameLoc));
> +        NewSSPtr = &NewSS;
> +      }
> +      if (Correction && (NNS || NewII != &II) &&
> +          // Ignore a correction to a template type as the to-be-corrected
> +          // identifier is not a template (typo correction for template names
> +          // is handled elsewhere).
> +          !(getLangOptions().CPlusPlus && NewSSPtr &&
> +            isTemplateName(S, *NewSSPtr, false, TemplateName, ParsedType(),
> +                           false, Template, MemberOfUnknownSpecialization))) {
> +        ParsedType Ty = getTypeName(*NewII, NameLoc, S, NewSSPtr,
> +                                    isClassName, HasTrailingDot, ObjectTypePtr,
> +                                    WantNontrivialTypeSourceInfo);
> +        if (Ty) {
> +          std::string CorrectedStr(Correction.getAsString(getLangOptions()));
> +          std::string CorrectedQuotedStr(
> +              Correction.getQuoted(getLangOptions()));
> +          Diag(NameLoc, diag::err_unknown_typename_suggest)
> +              << Result.getLookupName() << CorrectedQuotedStr
> +              << FixItHint::CreateReplacement(SourceRange(NameLoc),
> +                                              CorrectedStr);
> +          if (NamedDecl *FirstDecl = Correction.getCorrectionDecl())
> +            Diag(FirstDecl->getLocation(), diag::note_previous_decl)
> +              << CorrectedQuotedStr;
> +
> +          if (SS && NNS)
> +            SS->MakeTrivial(Context, NNS, SourceRange(NameLoc));
> +          *CorrectedII = NewII;
> +          return Ty;
> +        }
> +      }
> +    }
> +    // If typo correction failed or was not performed, fall through
>   case LookupResult::FoundOverloaded:
>   case LookupResult::FoundUnresolvedValue:
>     Result.suppressDiagnostics();
>
> Modified: cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp?rev=141621&r1=141620&r2=141621&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp (original)
> +++ cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp Mon Oct 10 20:02:41 2011
> @@ -1,8 +1,10 @@
>  // RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++0x-extensions %s
>
> -namespace fizbin { class Foobar; } // expected-note{{'fizbin::Foobar' declared here}}
> +namespace fizbin { class Foobar {}; } // expected-note 2 {{'fizbin::Foobar' declared here}} \
> +                                      // expected-note {{'Foobar' declared here}}
>  Foobar *my_bar  // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}}
> -    = new Foobar;  // expected-error{{expected a type}}
> +    = new Foobar; // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}}
> +fizbin::Foobar *my_foo = new fizbin::FooBar; // expected-error{{unknown type name 'FooBar'; did you mean 'Foobar'?}}
>
>  namespace barstool { int toFoobar() { return 1; } } // expected-note 3 {{'barstool::toFoobar' declared here}}
>  int Double(int x) { return x + x; }
> @@ -62,11 +64,13 @@
>
>  // Test case from http://llvm.org/bugs/show_bug.cgi?id=10318
>  namespace llvm {
> - template <typename T> class GraphWriter {}; // expected-note{{'llvm::GraphWriter' declared here}}
> + template <typename T> class GraphWriter {}; // expected-note {{'llvm::GraphWriter' declared here}} \
> +                                             // expected-note {{'GraphWriter' declared here}}
>  }
>
>  struct S {};
>  void bar() {
>  GraphWriter<S> x; //expected-error{{no template named 'GraphWriter'; did you mean 'llvm::GraphWriter'?}}
> -
> + (void)new llvm::GraphWriter; // expected-error {{expected a type}}
> + (void)new llvm::Graphwriter<S>; // expected-error {{no template named 'Graphwriter' in namespace 'llvm'; did you mean 'GraphWriter'?}}
>  }
>
> Added: cfe/trunk/test/SemaCXX/typo-correction.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typo-correction.cpp?rev=141621&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/typo-correction.cpp (added)
> +++ cfe/trunk/test/SemaCXX/typo-correction.cpp Mon Oct 10 20:02:41 2011
> @@ -0,0 +1,25 @@
> +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++0x-extensions %s
> +
> +struct errc {
> +  int v_;
> +  operator int() const {return v_;}
> +};
> +
> +class error_condition
> +{
> +  int _val_;
> +public:
> +  error_condition() : _val_(0) {}
> +
> +  error_condition(int _val)
> +    : _val_(_val) {}
> +
> +  template <class E>
> +  error_condition(E _e)
> +    {*this = make_error_condition(_e);}
> +
> +};
> +
> +inline error_condition make_error_condition(errc _e) {
> +  return error_condition(static_cast<int>(_e));
> +}

This test could use a comment explaining what it is actually testing.

-Eli




More information about the cfe-commits mailing list