diff options
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 80 | ||||
| -rw-r--r-- | clang/test/Index/complete-call.cpp | 68 | 
2 files changed, 98 insertions, 50 deletions
| diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 89cb9b53a47..b1df8f6232c 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6363,63 +6363,61 @@ bool Sema::diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND,  /// the overload candidate set.  void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,                                   ArrayRef<Expr *> Args, -                                 OverloadCandidateSet& CandidateSet, +                                 OverloadCandidateSet &CandidateSet,                                   TemplateArgumentListInfo *ExplicitTemplateArgs,                                   bool SuppressUserConversions,                                   bool PartialOverloading,                                   bool FirstArgumentIsBase) {    for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {      NamedDecl *D = F.getDecl()->getUnderlyingDecl(); -    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { -      ArrayRef<Expr *> FunctionArgs = Args; -      if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) { -        QualType ObjectType; -        Expr::Classification ObjectClassification; -        if (Args.size() > 0) { -          if (Expr *E = Args[0]) { -            // Use the explicit base to restrict the lookup: -            ObjectType = E->getType(); -            ObjectClassification = E->Classify(Context); -          } // .. else there is an implit base. -          FunctionArgs = Args.slice(1); -        } -        AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(), -                           cast<CXXMethodDecl>(FD)->getParent(), ObjectType, -                           ObjectClassification, FunctionArgs, CandidateSet, -                           SuppressUserConversions, PartialOverloading); -      } else { -        // Slice the first argument (which is the base) when we access -        // static method as non-static -        if (Args.size() > 0 && (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) && -                                             !isa<CXXConstructorDecl>(FD)))) { -          assert(cast<CXXMethodDecl>(FD)->isStatic()); -          FunctionArgs = Args.slice(1); -        } -        AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet, -                             SuppressUserConversions, PartialOverloading); -      } -    } else { -      FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D); -      if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) && -          !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) { -        QualType ObjectType; -        Expr::Classification ObjectClassification; +    ArrayRef<Expr *> FunctionArgs = Args; + +    FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D); +    FunctionDecl *FD = +        FunTmpl ? FunTmpl->getTemplatedDecl() : cast<FunctionDecl>(D); + +    if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) { +      QualType ObjectType; +      Expr::Classification ObjectClassification; +      if (Args.size() > 0) {          if (Expr *E = Args[0]) {            // Use the explicit base to restrict the lookup:            ObjectType = E->getType();            ObjectClassification = E->Classify(Context); -        } // .. else there is an implit base. +        } // .. else there is an implicit base. +        FunctionArgs = Args.slice(1); +      } +      if (FunTmpl) {          AddMethodTemplateCandidate(              FunTmpl, F.getPair(),              cast<CXXRecordDecl>(FunTmpl->getDeclContext()),              ExplicitTemplateArgs, ObjectType, ObjectClassification, -            Args.slice(1), CandidateSet, SuppressUserConversions, +            FunctionArgs, CandidateSet, SuppressUserConversions,              PartialOverloading);        } else { -        AddTemplateOverloadCandidate(FunTmpl, F.getPair(), -                                     ExplicitTemplateArgs, Args, -                                     CandidateSet, SuppressUserConversions, -                                     PartialOverloading); +        AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(), +                           cast<CXXMethodDecl>(FD)->getParent(), ObjectType, +                           ObjectClassification, FunctionArgs, CandidateSet, +                           SuppressUserConversions, PartialOverloading); +      } +    } else { +      // This branch handles both standalone functions and static methods. + +      // Slice the first argument (which is the base) when we access +      // static method as non-static. +      if (Args.size() > 0 && +          (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) && +                        !isa<CXXConstructorDecl>(FD)))) { +        assert(cast<CXXMethodDecl>(FD)->isStatic()); +        FunctionArgs = Args.slice(1); +      } +      if (FunTmpl) { +        AddTemplateOverloadCandidate( +            FunTmpl, F.getPair(), ExplicitTemplateArgs, FunctionArgs, +            CandidateSet, SuppressUserConversions, PartialOverloading); +      } else { +        AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet, +                             SuppressUserConversions, PartialOverloading);        }      }    } diff --git a/clang/test/Index/complete-call.cpp b/clang/test/Index/complete-call.cpp index ca116485ac9..84189a2aabe 100644 --- a/clang/test/Index/complete-call.cpp +++ b/clang/test/Index/complete-call.cpp @@ -109,12 +109,39 @@ void test() {  struct Bar2 : public Bar {    Bar2() {      Bar::foo_1(); -  } -}; - -// RUN: c-index-test -code-completion-at=%s:47:9 %s | FileCheck -check-prefix=CHECK-CC1 %s -// CHECK-CC1: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) -// CHECK-CC1: Completion contexts: +  }
 +};
 +
 +struct BarTemplates {
 +  static void foo_1() {}
 +  void foo_1(float) {}
 +  static void foo_1(int) {}
 +
 +  template<class T1, class T2>
 +  static void foo_1(T1 a, T2 b) { a + b; }
 +
 +  template<class T1, class T2>
 +  void foo_1(T1 a, T2 b, float c) { a + b + c; }
 +
 +  template<class T1, class T2>
 +  static void foo_1(T2 a, int b, T1 c)  { a + b + c; }
 +};
 +
 +void testTemplates() {
 +  BarTemplates::foo_1();
 +  BarTemplates b;
 +  b.foo_1();
 +}
 +
 +struct Bar2Template : public BarTemplates {
 +  Bar2Template() {
 +    BarTemplates::foo_1();
 +  }
 +};
 +
 +// RUN: c-index-test -code-completion-at=%s:47:9 %s | FileCheck -check-prefix=CHECK-CC1 %s
 +// CHECK-CC1: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
 +// CHECK-CC1: Completion contexts:
  // CHECK-CC1-NEXT: Any type  // CHECK-CC1-NEXT: Any value  // CHECK-CC1-NEXT: Enum tag @@ -860,7 +887,30 @@ struct Bar2 : public Bar {  // CHECK-CC62-NEXT: Enum tag  // CHECK-CC62-NEXT: Union tag  // CHECK-CC62-NEXT: Struct tag -// CHECK-CC62-NEXT: Class name -// CHECK-CC62-NEXT: Nested name specifier -// CHECK-CC62-NEXT: Objective-C interface +// CHECK-CC62-NEXT: Class name
 +// CHECK-CC62-NEXT: Nested name specifier
 +// CHECK-CC62-NEXT: Objective-C interface
 +
 +// RUN: c-index-test -code-completion-at=%s:131:23 %s | FileCheck -check-prefix=CHECK-CC63 %s
 +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
 +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1)
 +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1)
 +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1)
 +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1)
 +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1)
 +
 +// RUN: c-index-test -code-completion-at=%s:133:11 %s | FileCheck -check-prefix=CHECK-CC64 %s
 +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
 +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1)
 +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1)
 +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1)
 +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1)
 +
 +// RUN: c-index-test -code-completion-at=%s:138:25 %s | FileCheck -check-prefix=CHECK-CC65 %s
 +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
 +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1)
 +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1)
 +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1)
 +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1)
 +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1)
 | 

