@@ -988,9 +988,10 @@ namespace Cpp {
988
988
// encompassed in an anonymous namespace as follows.
989
989
namespace {
990
990
bool IsTemplatedFunction (Decl *D) {
991
- if ( llvm::isa_and_nonnull<FunctionTemplateDecl>(D))
992
- return true ;
991
+ return llvm::isa_and_nonnull<FunctionTemplateDecl>(D);
992
+ }
993
993
994
+ bool IsTemplateInstantiationOrSpecialization (Decl* D) {
994
995
if (auto *FD = llvm::dyn_cast_or_null<FunctionDecl>(D)) {
995
996
auto TK = FD->getTemplatedKind ();
996
997
return TK == FunctionDecl::TemplatedKind::
@@ -1013,9 +1014,12 @@ namespace Cpp {
1013
1014
bool IsTemplatedFunction (TCppFunction_t func)
1014
1015
{
1015
1016
auto *D = (Decl *) func;
1016
- return IsTemplatedFunction (D);
1017
+ return IsTemplatedFunction (D) || IsTemplateInstantiationOrSpecialization (D) ;
1017
1018
}
1018
1019
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
1019
1023
bool ExistsFunctionTemplate (const std::string& name,
1020
1024
TCppScope_t parent)
1021
1025
{
@@ -1031,38 +1035,70 @@ namespace Cpp {
1031
1035
return false ;
1032
1036
1033
1037
if ((intptr_t ) ND != (intptr_t ) -1 )
1034
- return IsTemplatedFunction (ND);
1038
+ return IsTemplatedFunction (ND) ||
1039
+ IsTemplateInstantiationOrSpecialization (ND);
1035
1040
1036
1041
// FIXME: Cycle through the Decls and check if there is a templated function
1037
1042
return true ;
1038
1043
}
1039
1044
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) {
1043
1048
auto * D = (Decl*)parent;
1044
1049
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
+ }
1047
1061
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 ;
1049
1067
1050
- llvm::StringRef Name (name);
1068
+ // Accumulate constructors
1069
+ LookupConstructors (name, parent, funcs);
1051
1070
auto & S = getSema ();
1071
+ D = GetUnderlyingScope (D);
1072
+ llvm::StringRef Name (name);
1052
1073
DeclarationName DName = &getASTContext ().Idents .get (name);
1053
1074
clang::LookupResult R (S, DName, SourceLocation (), Sema::LookupOrdinaryName,
1054
1075
For_Visible_Redeclaration);
1076
+ auto * DC = clang::Decl::castToDeclContext (D);
1077
+ Cpp_utils::Lookup::Named (&S, R, DC);
1055
1078
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 ;
1060
1081
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
+ }
1062
1093
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 ();
1066
1102
}
1067
1103
1068
1104
// Adapted from inner workings of Sema::BuildCallExpr
@@ -1185,6 +1221,8 @@ namespace Cpp {
1185
1221
bool IsConstructor (TCppConstFunction_t method)
1186
1222
{
1187
1223
const auto * D = static_cast <const Decl*>(method);
1224
+ if (const auto * FTD = dyn_cast<FunctionTemplateDecl>(D))
1225
+ return IsConstructor (FTD->getTemplatedDecl ());
1188
1226
return llvm::isa_and_nonnull<CXXConstructorDecl>(D);
1189
1227
}
1190
1228
0 commit comments