Skip to content

Commit d784fdb

Browse files
committed
Increase coverage and support FFI (e.g., for integration into my new bridle-ctl)
1 parent be5db4e commit d784fdb

8 files changed

Lines changed: 157 additions & 6 deletions

File tree

type_correct/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ set(Header_Files
2525
"StructAnalyzer.h"
2626
"TypeSolver.h"
2727
"CTU/FactManager.h"
28+
"TypeCorrectCAPI.h"
2829
)
2930
source_group("Header Files" FILES "${Header_Files}")
3031

@@ -35,6 +36,7 @@ set(Source_Files
3536
"StructAnalyzer.cpp"
3637
"TypeSolver.cpp"
3738
"CTU/FactManager.cpp"
39+
"TypeCorrectCAPI.cpp"
3840
)
3941
source_group("Source Files" FILES "${Source_Files}")
4042

@@ -159,5 +161,5 @@ install(FILES "${_export_file}" ${Header_Files}
159161
install(EXPORT "${LIBRARY_NAME}Targets" DESTINATION "${CMAKE_INSTALL_DATADIR}/${LIBRARY_NAME}")
160162

161163
# Redundant explicit install for verification (keeps original logic intact).
162-
install(FILES "${Header_Files}" "${Cli_Header_Files}" "${_export_file}"
164+
install(FILES ${Header_Files} ${Cli_Header_Files} "${_export_file}"
163165
TYPE "INCLUDE")

type_correct/TypeCorrect.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ TypeLoc GetBaseTypeLoc(TypeLoc TL) {
3737
TL = QTL.getUnqualifiedLoc();
3838
continue;
3939
}
40-
if (auto ETL = TL.getAs<ElaboratedTypeLoc>()) {
40+
#if LLVM_VERSION_MAJOR < 19
41+
if (auto ETL = TL.getAs<clang::ElaboratedTypeLoc>()) {
4142
TL = ETL.getNamedTypeLoc();
4243
continue;
4344
}
45+
#endif
4446
if (auto ATL = TL.getAs<AttributedTypeLoc>()) {
4547
TL = ATL.getModifiedLoc();
4648
continue;

type_correct/TypeCorrectCAPI.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#include "TypeCorrectCAPI.h"
2+
#include "TypeCorrectMain.h"
3+
4+
#include <clang/Tooling/CompilationDatabase.h>
5+
#include <clang/Tooling/Refactoring.h>
6+
#include <clang/Tooling/Tooling.h>
7+
#include <iostream>
8+
#include <vector>
9+
10+
namespace {
11+
class CAPIActionFactory : public clang::tooling::FrontendActionFactory {
12+
bool AuditMode;
13+
bool InPlace;
14+
public:
15+
CAPIActionFactory(bool AuditMode, bool InPlace)
16+
: AuditMode(AuditMode), InPlace(InPlace) {}
17+
18+
std::unique_ptr<clang::FrontendAction> create() override {
19+
return std::make_unique<TypeCorrectPluginAction>(
20+
"", "", InPlace, false, AuditMode,
21+
type_correct::Phase::Standalone, "", "");
22+
}
23+
};
24+
} // namespace
25+
26+
extern "C" TYPE_CORRECT_EXPORT int type_correct_audit(const char* target_path) {
27+
if (!target_path) return -1;
28+
29+
std::vector<std::string> CommandLine;
30+
auto Compilations = std::make_unique<clang::tooling::FixedCompilationDatabase>(".", CommandLine);
31+
32+
std::vector<std::string> SourcePaths = { target_path };
33+
clang::tooling::RefactoringTool Tool(*Compilations, SourcePaths);
34+
35+
CAPIActionFactory Factory(true /* AuditMode */, false /* InPlace */);
36+
return Tool.run(&Factory);
37+
}
38+
39+
extern "C" TYPE_CORRECT_EXPORT int type_correct_fix(const char* target_path, bool dry_run) {
40+
if (!target_path) return -1;
41+
42+
std::vector<std::string> CommandLine;
43+
auto Compilations = std::make_unique<clang::tooling::FixedCompilationDatabase>(".", CommandLine);
44+
45+
std::vector<std::string> SourcePaths = { target_path };
46+
clang::tooling::RefactoringTool Tool(*Compilations, SourcePaths);
47+
48+
bool InPlace = !dry_run;
49+
CAPIActionFactory Factory(false /* AuditMode */, InPlace);
50+
51+
if (dry_run) {
52+
return Tool.run(&Factory);
53+
} else {
54+
return Tool.runAndSave(&Factory);
55+
}
56+
}

type_correct/TypeCorrectCAPI.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* @file TypeCorrectCAPI.h
3+
* @brief Foreign Function Interface (FFI) for type-correct.
4+
*
5+
* Exposes core logic to external tooling (e.g., bridle-ctl) over C ABI.
6+
*/
7+
8+
#ifndef TYPE_CORRECT_CAPI_H
9+
#define TYPE_CORRECT_CAPI_H
10+
11+
#include "type_correct_export.h"
12+
#include <stdbool.h>
13+
14+
#ifdef __cplusplus
15+
extern "C" {
16+
#endif
17+
18+
/**
19+
* @brief Audits a target file using type-correct without applying changes.
20+
*
21+
* @param target_path The absolute or relative path to the C/C++ file to audit.
22+
* @return 0 on success, non-zero if issues were found or if an error occurred.
23+
*/
24+
TYPE_CORRECT_EXPORT int type_correct_audit(const char *target_path);
25+
26+
/**
27+
* @brief Fixes a target file using type-correct.
28+
*
29+
* @param target_path The absolute or relative path to the C/C++ file to fix.
30+
* @param dry_run If true, outputs the would-be changes instead of writing them
31+
* to disk.
32+
* @return 0 on success, non-zero if an error occurred.
33+
*/
34+
TYPE_CORRECT_EXPORT int type_correct_fix(const char *target_path, bool dry_run);
35+
36+
#ifdef __cplusplus
37+
}
38+
#endif
39+
40+
#endif /* TYPE_CORRECT_CAPI_H */

type_correct/TypeCorrectMain.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "TypeCorrect.h"
1717
#include "type_correct_export.h"
1818
#include <clang/Frontend/CompilerInstance.h>
19+
#include <clang/Frontend/FrontendAction.h>
1920
#include <clang/Rewrite/Core/Rewriter.h>
2021

2122
//===----------------------------------------------------------------------===//

type_correct/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ set(EXEC_NAME "test_type_correct")
3131
set(Source_Files
3232
"${EXEC_NAME}.cpp"
3333
"test_coverage.cpp"
34+
"test_capi.cpp"
3435
)
3536
source_group("${EXEC_NAME} Source Files" FILES "${Source_Files}")
3637

type_correct/tests/test_capi.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include <gtest/gtest.h>
2+
#include <gmock/gmock.h>
3+
#include "../TypeCorrectCAPI.h"
4+
#include <fstream>
5+
#include <llvm/Support/FileSystem.h>
6+
7+
TEST(TypeCorrectCAPI, AuditTest) {
8+
// Create a dummy file
9+
llvm::SmallString<128> tempPath;
10+
llvm::sys::fs::createTemporaryFile("test_audit", "cpp", tempPath);
11+
12+
std::ofstream out(tempPath.c_str());
13+
out << "int main() { return 0; }\n";
14+
out.close();
15+
16+
// Run audit
17+
int res = type_correct_audit(tempPath.c_str());
18+
EXPECT_EQ(res, 0);
19+
20+
// Run audit with null
21+
res = type_correct_audit(nullptr);
22+
EXPECT_EQ(res, -1);
23+
24+
llvm::sys::fs::remove(tempPath);
25+
}
26+
27+
TEST(TypeCorrectCAPI, FixTest) {
28+
// Create a dummy file
29+
llvm::SmallString<128> tempPath;
30+
llvm::sys::fs::createTemporaryFile("test_fix", "cpp", tempPath);
31+
32+
std::ofstream out(tempPath.c_str());
33+
out << "int main() { return 0; }\n";
34+
out.close();
35+
36+
// Run fix dry_run
37+
int res = type_correct_fix(tempPath.c_str(), true);
38+
EXPECT_EQ(res, 0);
39+
40+
// Run fix in_place
41+
res = type_correct_fix(tempPath.c_str(), false);
42+
EXPECT_EQ(res, 0);
43+
44+
// Run fix with null
45+
res = type_correct_fix(nullptr, false);
46+
EXPECT_EQ(res, -1);
47+
48+
llvm::sys::fs::remove(tempPath);
49+
}

type_correct/tests/test_coverage.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,8 @@ GTEST_TEST(Coverage, TypeSolverPaths) {
357357
EXPECT_TRUE(Solver.GetResolvedType(nullptr).isNull());
358358
EXPECT_FALSE(Solver.GetResolvedType(A).isNull());
359359

360-
QualType IncompleteTy = Ctx.getRecordType(Incomplete);
361-
QualType CompleteTy = Ctx.getRecordType(Complete);
360+
QualType IncompleteTy = Ctx.getCanonicalTagType(Incomplete);
361+
QualType CompleteTy = Ctx.getCanonicalTagType(Complete);
362362
EXPECT_FALSE(Solver.GetWider(QualType(), Ctx.IntTy, &Ctx).isNull());
363363
Solver.GetWider(Ctx.IntTy, QualType(), &Ctx);
364364
Solver.GetWider(Ctx.IntTy, Ctx.IntTy, &Ctx);
@@ -972,8 +972,8 @@ GTEST_TEST(Coverage, TypeCorrectHelperFunctions) {
972972
const RecordDecl *FooRec = FindRecordDecl(Ctx, "Foo");
973973
ASSERT_NE(Fwd, nullptr);
974974
ASSERT_NE(FooRec, nullptr);
975-
QualType IncompleteTy = Ctx.getRecordType(Fwd);
976-
QualType CompleteTy = Ctx.getRecordType(FooRec);
975+
QualType IncompleteTy = Ctx.getCanonicalTagType(Fwd);
976+
QualType CompleteTy = Ctx.getCanonicalTagType(FooRec);
977977

978978
type_correct::test_support::GetWiderTypeForTest(QualType(), Ctx.IntTy, Ctx);
979979
type_correct::test_support::GetWiderTypeForTest(Ctx.IntTy, QualType(), Ctx);

0 commit comments

Comments
 (0)