[cfe-commits] r136807 - in /cfe/trunk: include/clang/Sema/Sema.h include/clang/Sema/TypoCorrection.h lib/Sema/SemaExpr.cpp lib/Sema/SemaLookup.cpp lib/Sema/SemaOverload.cpp test/FixIt/typo-crash.cpp test/SemaCXX/function-overload-typo-crash.cpp

Kaelyn Uhrain rikka at google.com
Wed Aug 3 13:36:05 PDT 2011


Author: rikka
Date: Wed Aug  3 15:36:05 2011
New Revision: 136807

URL: http://llvm.org/viewvc/llvm-project?rev=136807&view=rev
Log:
Improve overloaded function handling in the typo correction code.

Change TypoCorrection to store a set of NamedDecls instead of a single
NamedDecl. Also add initial support for performing function overload
resolution to Sema::DiagnoseEmptyLookup.

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Sema/TypoCorrection.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/FixIt/typo-crash.cpp
    cfe/trunk/test/SemaCXX/function-overload-typo-crash.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=136807&r1=136806&r2=136807&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Aug  3 15:36:05 2011
@@ -2236,7 +2236,8 @@
                               const TemplateArgumentListInfo *&TemplateArgs);
 
   bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
-                           CorrectTypoContext CTC = CTC_Unknown);
+                           CorrectTypoContext CTC = CTC_Unknown,
+                           Expr **Args = 0, unsigned NumArgs = 0);
 
   ExprResult LookupInObjCMethod(LookupResult &R, Scope *S, IdentifierInfo *II,
                                 bool AllowBuiltinCreation=false);

Modified: cfe/trunk/include/clang/Sema/TypoCorrection.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/TypoCorrection.h?rev=136807&r1=136806&r2=136807&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/TypoCorrection.h (original)
+++ cfe/trunk/include/clang/Sema/TypoCorrection.h Wed Aug  3 15:36:05 2011
@@ -16,6 +16,7 @@
 #define LLVM_CLANG_SEMA_TYPOCORRECTION_H
 
 #include "clang/AST/DeclCXX.h"
+#include "llvm/ADT/SmallVector.h"
 
 namespace clang {
 
@@ -23,29 +24,31 @@
 class TypoCorrection {
 public:
   TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl,
-                 NestedNameSpecifier *NNS=NULL, unsigned distance=0)
+                 NestedNameSpecifier *NNS=0, unsigned distance=0)
       : CorrectionName(Name),
         CorrectionNameSpec(NNS),
-        CorrectionDecl(NameDecl),
-        EditDistance(distance) {}
+        EditDistance(distance) {
+    if (NameDecl)
+      CorrectionDecls.push_back(NameDecl);
+  }
 
-  TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS=NULL,
+  TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS=0,
                  unsigned distance=0)
       : CorrectionName(Name->getDeclName()),
         CorrectionNameSpec(NNS),
-        CorrectionDecl(Name),
-        EditDistance(distance)  {}
+        EditDistance(distance) {
+    if (Name)
+      CorrectionDecls.push_back(Name);
+  }
 
-  TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS=NULL,
+  TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS=0,
                  unsigned distance=0)
       : CorrectionName(Name),
         CorrectionNameSpec(NNS),
-        CorrectionDecl(NULL),
-        EditDistance(distance)  {}
+        EditDistance(distance) {}
 
   TypoCorrection()
-      : CorrectionName(), CorrectionNameSpec(NULL), CorrectionDecl(NULL),
-        EditDistance(0) {}
+      : CorrectionNameSpec(0), EditDistance(0) {}
 
   /// \brief Gets the DeclarationName of the typo correction
   DeclarationName getCorrection() const { return CorrectionName; }
@@ -66,37 +69,67 @@
 
   /// \brief Gets the pointer to the declaration of the typo correction
   NamedDecl* getCorrectionDecl() const {
-    return isKeyword() ? NULL : CorrectionDecl;
+    return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : 0;
   }
   template <class DeclClass>
   DeclClass *getCorrectionDeclAs() const {
     return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
   }
   
+  /// \brief Clears the list of NamedDecls before adding the new one.
   void setCorrectionDecl(NamedDecl *CDecl) {
-    CorrectionDecl = CDecl;
-    if (!CorrectionName)
-      CorrectionName = CDecl->getDeclName();
+    CorrectionDecls.clear();
+    addCorrectionDecl(CDecl);
   }
 
+  /// \brief Add the given NamedDecl to the list of NamedDecls that are the
+  /// declarations associated with the DeclarationName of this TypoCorrection
+  void addCorrectionDecl(NamedDecl *CDecl);
+
   std::string getAsString(const LangOptions &LO) const;
   std::string getQuoted(const LangOptions &LO) const {
     return "'" + getAsString(LO) + "'";
   }
 
+  /// \brief Returns whether this TypoCorrection has a non-empty DeclarationName
   operator bool() const { return bool(CorrectionName); }
 
-  static inline NamedDecl *KeywordDecl() { return (NamedDecl*)-1; }
-  bool isKeyword() const { return CorrectionDecl == KeywordDecl(); }
+  /// \brief Mark this TypoCorrection as being a keyword.
+  /// Since addCorrectionDeclsand setCorrectionDecl don't allow NULL to be
+  /// added to the list of the correction's NamedDecl pointers, NULL is added
+  /// as the only element in the list to mark this TypoCorrection as a keyword.
+  void makeKeyword() {
+    CorrectionDecls.clear();
+    CorrectionDecls.push_back(0);
+  }
+
+  // Check if this TypoCorrection is a keyword by checking if the first
+  // item in CorrectionDecls is NULL.
+  bool isKeyword() const {
+    return !CorrectionDecls.empty() &&
+        CorrectionDecls.front() == 0;
+  }
 
   // Returns true if the correction either is a keyword or has a known decl.
-  bool isResolved() const { return CorrectionDecl != NULL; }
+  bool isResolved() const { return !CorrectionDecls.empty(); }
+
+  bool isOverloaded() const {
+    return CorrectionDecls.size() > 1;
+  }
+
+  typedef llvm::SmallVector<NamedDecl*, 1>::iterator decl_iterator;
+  decl_iterator begin() { return CorrectionDecls.begin(); }
+  decl_iterator end() { return CorrectionDecls.end(); }
 
 private:
+  bool hasCorrectionDecl() const {
+    return (!isKeyword() && !CorrectionDecls.empty());
+  }
+
   // Results.
   DeclarationName CorrectionName;
   NestedNameSpecifier *CorrectionNameSpec;
-  NamedDecl *CorrectionDecl;
+  llvm::SmallVector<NamedDecl*, 1> CorrectionDecls;
   unsigned EditDistance;
 };
 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=136807&r1=136806&r2=136807&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Aug  3 15:36:05 2011
@@ -1364,7 +1364,8 @@
 ///
 /// \return false if new lookup candidates were found
 bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
-                               CorrectTypoContext CTC) {
+                               CorrectTypoContext CTC, Expr **Args,
+                               unsigned NumArgs) {
   DeclarationName Name = R.getLookupName();
 
   unsigned diagnostic = diag::err_undeclared_var_use;
@@ -1450,6 +1451,27 @@
     R.setLookupName(Corrected.getCorrection());
 
     if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
+      if (Corrected.isOverloaded()) {
+        OverloadCandidateSet OCS(R.getNameLoc());
+        OverloadCandidateSet::iterator Best;
+        for (TypoCorrection::decl_iterator CD = Corrected.begin(),
+                                        CDEnd = Corrected.end();
+             CD != CDEnd; ++CD) {
+          if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*CD))
+            AddOverloadCandidate(FD, DeclAccessPair::make(*CD, AS_none),
+                                 Args, NumArgs, OCS);
+          // TODO: Handle FunctionTemplateDecl and other Decl types that
+          // support overloading and could be corrected by CorrectTypo.
+        }
+        switch (OCS.BestViableFunction(*this, R.getNameLoc(), Best)) {
+          case OR_Success:
+            ND = Best->Function;
+            break;
+          default:
+            // Don't try to recover; it won't work.
+            return true;
+        }
+      }
       R.addDecl(ND);
       if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
         if (SS.isEmpty())

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=136807&r1=136806&r2=136807&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed Aug  3 15:36:05 2011
@@ -3020,7 +3020,7 @@
   void FoundName(StringRef Name);
   void addKeywordResult(StringRef Keyword);
   void addName(StringRef Name, NamedDecl *ND, unsigned Distance,
-               NestedNameSpecifier *NNS=NULL);
+               NestedNameSpecifier *NNS=NULL, bool isKeyword=false);
   void addCorrection(TypoCorrection Correction);
 
   typedef TypoResultsMap::iterator result_iterator;
@@ -3099,15 +3099,17 @@
     return;
   }
 
-  addName(Keyword, TypoCorrection::KeywordDecl(), ED);
+  addName(Keyword, NULL, ED, NULL, true);
 }
 
 void TypoCorrectionConsumer::addName(StringRef Name,
                                      NamedDecl *ND,
                                      unsigned Distance,
-                                     NestedNameSpecifier *NNS) {
-  addCorrection(TypoCorrection(&SemaRef.Context.Idents.get(Name),
-                               ND, NNS, Distance));
+                                     NestedNameSpecifier *NNS,
+                                     bool isKeyword) {
+  TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, Distance);
+  if (isKeyword) TC.makeKeyword();
+  addCorrection(TC);
 }
 
 void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
@@ -3677,12 +3679,19 @@
         // We don't deal with ambiguities.
         return TypoCorrection();
 
+      case LookupResult::FoundOverloaded: {
+        // Store all of the Decls for overloaded symbols
+        for (LookupResult::iterator TRD = TmpRes.begin(),
+                                 TRDEnd = TmpRes.end();
+             TRD != TRDEnd; ++TRD)
+          I->second.addCorrectionDecl(*TRD);
+        ++I;
+        break;
+      }
+
       case LookupResult::Found:
-      case LookupResult::FoundOverloaded:
       case LookupResult::FoundUnresolvedValue:
         I->second.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
-        // FIXME: This sets the CorrectionDecl to NULL for overloaded functions.
-        // It would be nice to find the right one with overload resolution.
         ++I;
         break;
       }
@@ -3718,11 +3727,20 @@
 
           switch (TmpRes.getResultKind()) {
           case LookupResult::Found:
-          case LookupResult::FoundOverloaded:
           case LookupResult::FoundUnresolvedValue:
             Consumer.addName((*QRI)->getName(), TmpRes.getAsSingle<NamedDecl>(),
                              QualifiedED, NI->NameSpecifier);
             break;
+          case LookupResult::FoundOverloaded: {
+            TypoCorrection corr(&Context.Idents.get((*QRI)->getName()), NULL,
+                                NI->NameSpecifier, QualifiedED);
+            for (LookupResult::iterator TRD = TmpRes.begin(),
+                                     TRDEnd = TmpRes.end();
+                 TRD != TRDEnd; ++TRD)
+              corr.addCorrectionDecl(*TRD);
+            Consumer.addCorrection(corr);
+            break;
+          }
           case LookupResult::NotFound:
           case LookupResult::NotFoundInCurrentInstantiation:
           case LookupResult::Ambiguous:
@@ -3802,6 +3820,18 @@
   return TypoCorrection();
 }
 
+void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) {
+  if (!CDecl) return;
+
+  if (isKeyword())
+    CorrectionDecls.clear();
+
+  CorrectionDecls.push_back(CDecl);
+
+  if (!CorrectionName)
+    CorrectionName = CDecl->getDeclName();
+}
+
 std::string TypoCorrection::getAsString(const LangOptions &LO) const {
   if (CorrectionNameSpec) {
     std::string tmpBuffer;

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=136807&r1=136806&r2=136807&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Aug  3 15:36:05 2011
@@ -8220,7 +8220,8 @@
   if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R,
                               ExplicitTemplateArgs, Args, NumArgs) &&
       (!EmptyLookup ||
-       SemaRef.DiagnoseEmptyLookup(S, SS, R, Sema::CTC_Expression)))
+       SemaRef.DiagnoseEmptyLookup(S, SS, R, Sema::CTC_Expression,
+                                   Args, NumArgs)))
     return ExprError();
 
   assert(!R.empty() && "lookup results empty despite recovery");

Modified: cfe/trunk/test/FixIt/typo-crash.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/typo-crash.cpp?rev=136807&r1=136806&r2=136807&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/typo-crash.cpp (original)
+++ cfe/trunk/test/FixIt/typo-crash.cpp Wed Aug  3 15:36:05 2011
@@ -3,9 +3,10 @@
 // FIXME: The diagnostics and recovery here are very, very poor.
 
 // PR10355
-template<typename T> void template_id1() {
-  template_id2<> t; // expected-error 2{{use of undeclared identifier 'template_id2'; did you mean 'template_id1'?}} \
-  // expected-error{{expected expression}} \
-  // expected-error{{use of undeclared identifier 't'}}
+template<typename T> void template_id1() { // expected-note {{'template_id1' declared here}} \
+  // expected-note {{candidate function}}
+  template_id2<> t; // expected-error {{no template named 'template_id2'; did you mean 'template_id1'?}} \
+  // expected-error {{expected ';' after expression}} \
+  // expected-error {{cannot resolve overloaded function 'template_id1' from context}} \
+  // expected-error {{use of undeclared identifier 't'}}
  }
-

Modified: cfe/trunk/test/SemaCXX/function-overload-typo-crash.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/function-overload-typo-crash.cpp?rev=136807&r1=136806&r2=136807&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/function-overload-typo-crash.cpp (original)
+++ cfe/trunk/test/SemaCXX/function-overload-typo-crash.cpp Wed Aug  3 15:36:05 2011
@@ -1,10 +1,10 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
 // PR10283
-void min();
+void min(); //expected-note {{'min' declared here}}
 void min(int);
 
-template <typename T> void max(T);
+template <typename T> void max(T); //expected-note {{'max' declared here}}
 
 void f() {
   fin(); //expected-error {{use of undeclared identifier 'fin'; did you mean 'min'}}





More information about the cfe-commits mailing list