@@ -978,9 +978,10 @@ namespace Cpp {
978978 // encompassed in an anonymous namespace as follows.
979979 namespace {
980980 bool IsTemplatedFunction (Decl *D) {
981- if ( llvm::isa_and_nonnull<FunctionTemplateDecl>(D))
982- return true ;
981+ return llvm::isa_and_nonnull<FunctionTemplateDecl>(D);
982+ }
983983
984+ bool IsTemplateInstantiationOrSpecialization (Decl* D) {
984985 if (auto *FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
985986 auto TK = FD->getTemplatedKind ();
986987 return TK == FunctionDecl::TemplatedKind::
@@ -1003,9 +1004,12 @@ namespace Cpp {
10031004 bool IsTemplatedFunction (TCppFunction_t func)
10041005 {
10051006 auto *D = (Decl *) func;
1006- return IsTemplatedFunction (D);
1007+ return IsTemplatedFunction (D) || IsTemplateInstantiationOrSpecialization (D) ;
10071008 }
10081009
1010+ // FIXME: This lookup is broken, and should no longer be used in favour of
1011+ // `GetClassTemplatedMethods` If the candidate set returned is =1, that means
1012+ // the template function exists and >1 means overloads
10091013 bool ExistsFunctionTemplate (const std::string& name,
10101014 TCppScope_t parent)
10111015 {
@@ -1021,38 +1025,70 @@ namespace Cpp {
10211025 return false ;
10221026
10231027 if ((intptr_t ) ND != (intptr_t ) -1 )
1024- return IsTemplatedFunction (ND);
1028+ return IsTemplatedFunction (ND) ||
1029+ IsTemplateInstantiationOrSpecialization (ND);
10251030
10261031 // FIXME: Cycle through the Decls and check if there is a templated function
10271032 return true ;
10281033 }
10291034
1030- void GetClassTemplatedMethods (const std::string& name, TCppScope_t parent,
1031- std::vector<TCppFunction_t>& funcs) {
1035+ // Looks up all constructors in the current DeclContext
1036+ void LookupConstructors (const std::string& name, TCppScope_t parent,
1037+ std::vector<TCppFunction_t>& funcs) {
10321038
10331039 auto * D = (Decl*)parent;
10341040
1035- if (!parent || name.empty ())
1036- return ;
1041+ if (auto * CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(D)) {
1042+ getSema ().ForceDeclarationOfImplicitMembers (CXXRD);
1043+ DeclContextLookupResult Result = getSema ().LookupConstructors (CXXRD);
1044+ // Obtaining all constructors when we intend to lookup a method under a
1045+ // scope can lead to crashes. We avoid that by accumulating constructors
1046+ // only if the Decl matches the lookup name.
1047+ if (!Result.empty ())
1048+ for (auto * i : Result)
1049+ if (GetName (i) == name)
1050+ funcs.push_back (i);
1051+ }
1052+ }
10371053
1038- D = GetUnderlyingScope (D);
1054+ bool GetClassTemplatedMethods (const std::string& name, TCppScope_t parent,
1055+ std::vector<TCppFunction_t>& funcs) {
1056+ auto * D = (Decl*)parent;
1057+ if (!D && name.empty ())
1058+ return false ;
10391059
1040- llvm::StringRef Name (name);
1060+ // Accumulate constructors
1061+ LookupConstructors (name, parent, funcs);
10411062 auto & S = getSema ();
1063+ D = GetUnderlyingScope (D);
1064+ llvm::StringRef Name (name);
10421065 DeclarationName DName = &getASTContext ().Idents .get (name);
10431066 clang::LookupResult R (S, DName, SourceLocation (), Sema::LookupOrdinaryName,
1044- For_Visible_Redeclaration);
1067+ Sema::NotForRedeclaration);
1068+ auto DC = clang::Decl::castToDeclContext (D);
1069+ Cpp_utils::Lookup::Named (&S, R, DC);
10451070
1046- Cpp_utils::Lookup::Named (&S, R, Decl::castToDeclContext (D));
1047-
1048- if (R.empty ())
1049- return ;
1071+ // Distinct match, single Decl
1072+ if (R.getResultKind () == clang::LookupResult::Found) {
1073+ funcs.push_back (R.getFoundDecl ());
1074+ }
1075+ // Loop over overload set
1076+ else if (R.getResultKind () == clang::LookupResult::FoundOverloaded) {
1077+ for (auto * Found : R)
1078+ if (IsTemplatedFunction (Found))
1079+ funcs.push_back (Found);
1080+ }
10501081
1051- R.resolveKind ();
1082+ // Ambiguously found
1083+ // FIXME : if result not empty, add them anyway?
1084+ else {
1085+ if (!R.empty ()) {
1086+ for (auto * Found : R)
1087+ funcs.push_back (Found);
1088+ }
1089+ }
10521090
1053- for (auto * Found : R)
1054- if (llvm::isa<FunctionTemplateDecl>(Found))
1055- funcs.push_back (Found);
1091+ return !funcs.empty ();
10561092 }
10571093
10581094 // Adapted from inner workings of Sema::BuildCallExpr
@@ -1175,6 +1211,8 @@ namespace Cpp {
11751211 bool IsConstructor (TCppConstFunction_t method)
11761212 {
11771213 const auto * D = static_cast <const Decl*>(method);
1214+ if (const auto * FTD = dyn_cast<FunctionTemplateDecl>(D))
1215+ return IsConstructor (FTD->getTemplatedDecl ());
11781216 return llvm::isa_and_nonnull<CXXConstructorDecl>(D);
11791217 }
11801218
0 commit comments