Skip to content

Commit b14bf55

Browse files
authored
annotate overloaded private class members where needed (#51)
## Purpose Running IDs across the LLVM source, I observed a few cases where private methods that should have been annotated due to being referenced in the same translation unit. In these instances, the missed private methods had overloads and their references were ambiguous. This PR addresses the issue and makes IDS properly flag these methods for export. ## Overview 1. Override `VisitUnresolvedMemberExpr` which gets called in this scenario. Invoke the existing `export_function_if_needed` for each method declaration the expression may reference. This is only done for private methods because public methods will always be annotated. 2. Add a new test case. For this test force Clang language options to `-fno-delayed-template-parsing`, which is already the default on Linux and Darwin. This is required on Windows, where the default behavior is `-fdelayed-template-parsing` to better match MSVC behavior. More details [here](https://clang.llvm.org/docs/MSVCCompatibility.html). Without this argument, the new test case does not pass when run on Windows. ## Validation 1. New tests case. 2. Ran tests on Windows and Linux. 3. Manually ran on a subset of the llvm headers and inspected results.
1 parent c48649d commit b14bf55

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

Sources/idt/idt.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,19 @@ class visitor : public clang::RecursiveASTVisitor<visitor> {
514514
return true;
515515
}
516516

517+
// Visit every unresolved member expression in the compilation unit to
518+
// determine if there are overloaded private methods that might be called. In
519+
// this uncommon case, the private method should be annotated.
520+
bool VisitUnresolvedMemberExpr(clang::UnresolvedMemberExpr *E) {
521+
// Iterate over potential declarations
522+
for (const clang::NamedDecl *ND : E->decls())
523+
if (const auto *MD = llvm::dyn_cast<clang::CXXMethodDecl>(ND))
524+
if (MD->getAccess() == clang::AccessSpecifier::AS_private)
525+
export_function_if_needed(MD);
526+
527+
return true;
528+
}
529+
517530
// Visit every constructor call in the compilation unit to determine if there
518531
// are any inline calls to private constructors. In this uncommon case, the
519532
// private constructor must be annotated for export. Constructor calls are not

Tests/TemplateCallsPrivateMethod.hh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %idt --extra-arg="-fno-delayed-template-parsing" --export-macro IDT_TEST_ABI %s 2>&1 | %FileCheck %s
2+
3+
class TemplateCallsPrivateMethod {
4+
public:
5+
// CHECK-NOT: TemplateCallsPrvateMethod.hh:[[@LINE+1]]:{{.*}}
6+
template <typename T> void publicTemplateMethod(T x) {
7+
privateMethodForTemplate(x);
8+
}
9+
10+
private:
11+
// NOTE: we use CHECK-DAG here because these remarks may come out of order and
12+
// we cannot control the order by rearranging members.
13+
14+
// CHECK-DAG: TemplateCallsPrivateMethod.hh:[[@LINE+1]]:3: remark: unexported public interface 'privateMethodForTemplate'
15+
void privateMethodForTemplate(long x) const;
16+
17+
// CHECK-DAG: TemplateCallsPrivateMethod.hh:[[@LINE+1]]:3: remark: unexported public interface 'privateMethodForTemplate'
18+
void privateMethodForTemplate(int x) const;
19+
};
20+

0 commit comments

Comments
 (0)