diff --git a/Sources/idt/idt.cc b/Sources/idt/idt.cc index a394fd0..cfc7d2b 100644 --- a/Sources/idt/idt.cc +++ b/Sources/idt/idt.cc @@ -514,6 +514,19 @@ class visitor : public clang::RecursiveASTVisitor { return true; } + // Visit every unresolved member expression in the compilation unit to + // determine if there are overloaded private methods that might be called. In + // this uncommon case, the private method should be annotated. + bool VisitUnresolvedMemberExpr(clang::UnresolvedMemberExpr *E) { + // Iterate over potential declarations + for (const clang::NamedDecl *ND : E->decls()) + if (const auto *MD = llvm::dyn_cast(ND)) + if (MD->getAccess() == clang::AccessSpecifier::AS_private) + export_function_if_needed(MD); + + return true; + } + // Visit every constructor call in the compilation unit to determine if there // are any inline calls to private constructors. In this uncommon case, the // private constructor must be annotated for export. Constructor calls are not diff --git a/Tests/TemplateCallsPrivateMethod.hh b/Tests/TemplateCallsPrivateMethod.hh new file mode 100644 index 0000000..9c66401 --- /dev/null +++ b/Tests/TemplateCallsPrivateMethod.hh @@ -0,0 +1,20 @@ +// RUN: %idt --extra-arg="-fno-delayed-template-parsing" --export-macro IDT_TEST_ABI %s 2>&1 | %FileCheck %s + +class TemplateCallsPrivateMethod { +public: + // CHECK-NOT: TemplateCallsPrvateMethod.hh:[[@LINE+1]]:{{.*}} + template void publicTemplateMethod(T x) { + privateMethodForTemplate(x); + } + +private: + // NOTE: we use CHECK-DAG here because these remarks may come out of order and + // we cannot control the order by rearranging members. + + // CHECK-DAG: TemplateCallsPrivateMethod.hh:[[@LINE+1]]:3: remark: unexported public interface 'privateMethodForTemplate' + void privateMethodForTemplate(long x) const; + + // CHECK-DAG: TemplateCallsPrivateMethod.hh:[[@LINE+1]]:3: remark: unexported public interface 'privateMethodForTemplate' + void privateMethodForTemplate(int x) const; +}; +