@@ -988,9 +988,10 @@ namespace Cpp {
988988 // encompassed in an anonymous namespace as follows.
989989 namespace {
990990 bool IsTemplatedFunction (Decl *D) {
991- if ( llvm::isa_and_nonnull<FunctionTemplateDecl>(D))
992- return true ;
991+ return llvm::isa_and_nonnull<FunctionTemplateDecl>(D);
992+ }
993993
994+ bool IsTemplateInstantiationOrSpecialization (Decl* D) {
994995 if (auto *FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
995996 auto TK = FD->getTemplatedKind ();
996997 return TK == FunctionDecl::TemplatedKind::
@@ -1013,9 +1014,12 @@ namespace Cpp {
10131014 bool IsTemplatedFunction (TCppFunction_t func)
10141015 {
10151016 auto *D = (Decl *) func;
1016- return IsTemplatedFunction (D);
1017+ return IsTemplatedFunction (D) || IsTemplateInstantiationOrSpecialization (D) ;
10171018 }
10181019
1020+ // FIXME: This lookup is broken, and should no longer be used in favour of
1021+ // `GetClassTemplatedMethods` If the candidate set returned is =1, that means
1022+ // the template function exists and >1 means overloads
10191023 bool ExistsFunctionTemplate (const std::string& name,
10201024 TCppScope_t parent)
10211025 {
@@ -1031,38 +1035,70 @@ namespace Cpp {
10311035 return false ;
10321036
10331037 if ((intptr_t ) ND != (intptr_t ) -1 )
1034- return IsTemplatedFunction (ND);
1038+ return IsTemplatedFunction (ND) ||
1039+ IsTemplateInstantiationOrSpecialization (ND);
10351040
10361041 // FIXME: Cycle through the Decls and check if there is a templated function
10371042 return true ;
10381043 }
10391044
1040- void GetClassTemplatedMethods ( const std::string& name, TCppScope_t parent,
1041- std::vector<TCppFunction_t>& funcs) {
1042-
1045+ // Looks up all constructors in the current DeclContext
1046+ void LookupConstructors ( const std::string& name, TCppScope_t parent,
1047+ std::vector<TCppFunction_t>& funcs) {
10431048 auto * D = (Decl*)parent;
10441049
1045- if (!parent || name.empty ())
1046- return ;
1050+ if (auto * CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
1051+ getSema ().ForceDeclarationOfImplicitMembers (CXXRD);
1052+ DeclContextLookupResult Result = getSema ().LookupConstructors (CXXRD);
1053+ // Obtaining all constructors when we intend to lookup a method under a
1054+ // scope can lead to crashes. We avoid that by accumulating constructors
1055+ // only if the Decl matches the lookup name.
1056+ for (auto * i : Result)
1057+ if (GetName (i) == name)
1058+ funcs.push_back (i);
1059+ }
1060+ }
10471061
1048- D = GetUnderlyingScope (D);
1062+ bool GetClassTemplatedMethods (const std::string& name, TCppScope_t parent,
1063+ std::vector<TCppFunction_t>& funcs) {
1064+ auto * D = (Decl*)parent;
1065+ if (!D && name.empty ())
1066+ return false ;
10491067
1050- llvm::StringRef Name (name);
1068+ // Accumulate constructors
1069+ LookupConstructors (name, parent, funcs);
10511070 auto & S = getSema ();
1071+ D = GetUnderlyingScope (D);
1072+ llvm::StringRef Name (name);
10521073 DeclarationName DName = &getASTContext ().Idents .get (name);
10531074 clang::LookupResult R (S, DName, SourceLocation (), Sema::LookupOrdinaryName,
10541075 For_Visible_Redeclaration);
1076+ auto * DC = clang::Decl::castToDeclContext (D);
1077+ Cpp_utils::Lookup::Named (&S, R, DC);
10551078
1056- Cpp_utils::Lookup::Named (&S, R, Decl::castToDeclContext (D));
1057-
1058- if (R.empty ())
1059- return ;
1079+ if (R.getResultKind () == clang::LookupResult::NotFound && funcs.empty ())
1080+ return false ;
10601081
1061- R.resolveKind ();
1082+ // Distinct match, single Decl
1083+ else if (R.getResultKind () == clang::LookupResult::Found) {
1084+ if (IsTemplatedFunction (R.getFoundDecl ()))
1085+ funcs.push_back (R.getFoundDecl ());
1086+ }
1087+ // Loop over overload set
1088+ else if (R.getResultKind () == clang::LookupResult::FoundOverloaded) {
1089+ for (auto * Found : R)
1090+ if (IsTemplatedFunction (Found))
1091+ funcs.push_back (Found);
1092+ }
10621093
1063- for (auto * Found : R)
1064- if (llvm::isa<FunctionTemplateDecl>(Found))
1065- funcs.push_back (Found);
1094+ // TODO: Handle ambiguously found LookupResult
1095+ // else if (R.getResultKind() == clang::LookupResult::Ambiguous) {
1096+ // auto kind = R.getAmbiguityKind();
1097+ // ...
1098+ // Produce a diagnostic describing the ambiguity that resulted
1099+ // from name lookup as done in Sema::DiagnoseAmbiguousLookup
1100+ //
1101+ return !funcs.empty ();
10661102 }
10671103
10681104 // Adapted from inner workings of Sema::BuildCallExpr
@@ -1185,6 +1221,8 @@ namespace Cpp {
11851221 bool IsConstructor (TCppConstFunction_t method)
11861222 {
11871223 const auto * D = static_cast <const Decl*>(method);
1224+ if (const auto * FTD = dyn_cast<FunctionTemplateDecl>(D))
1225+ return IsConstructor (FTD->getTemplatedDecl ());
11881226 return llvm::isa_and_nonnull<CXXConstructorDecl>(D);
11891227 }
11901228
0 commit comments