Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,10 @@ def TrustReturnsNonnullChecker : Checker<"TrustReturnsNonnull">,
"are not null">,
Documentation<NotDocumented>;

def ThreadModeling : Checker<"Thread">,
HelpText<"Make threaded code available to other checkers.">,
Documentation<NotDocumented>;

} // end "apiModeling"

//===----------------------------------------------------------------------===//
Expand Down
1 change: 1 addition & 0 deletions clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ add_clang_library(clangStaticAnalyzerCheckers
Taint.cpp
TaintTesterChecker.cpp
TestAfterDivZeroChecker.cpp
ThreadModeling.cpp
TraversalChecker.cpp
TrustNonnullChecker.cpp
TrustReturnsNonnullChecker.cpp
Expand Down
74 changes: 74 additions & 0 deletions clang/lib/StaticAnalyzer/Checkers/ThreadModeling.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@


#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"

#include <clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h>

using namespace clang;
using namespace ento;

namespace {

// Since we are looking to extract the arguments, go with pre call for now
class ThreadModeling : public Checker<check::PreCall> {

constexpr static CallDescriptionSet ThreadCreateCalls {
{ CDM::CLibrary, {"pthread_create"}, 4},
};

const FunctionDecl *GetFunctionDecl(SVal V, CheckerContext &C) const;
public:
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
};

} // end anonymous namespace


void ThreadModeling::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
if (!ThreadCreateCalls.contains(Call)) {
return;
}

// 1. Get the `start_routine` argument
ProgramStateRef State = C.getState();
const FunctionDecl *CreateCall = reinterpret_cast<const FunctionDecl*>(Call.getDecl());

// 2. Extract the start_routine parameter
/* int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void *),
void *restrict arg);
*/
assert(Call.getNumArgs() == 4 && "pthread_create(3) should have 4 arguments");
const Expr *StartRoutineExpr = Call.getArgExpr(2);
assert(StartRoutineExpr && "start_routine should exist"); // XXX: might fail if in diff TU?

// 3. Get the function pointer for `start_routine`
const SVal SRV = C.getSVal(StartRoutineExpr);

// 4. Resolve FunctionDecl
// 5. Get AST (single TU for now)
// 6. Resolve AST to Call
// 7. Inline Call


}

const FunctionDecl *ThreadModeling::GetFunctionDecl(SVal V, CheckerContext &C) const {
if (const FunctionDecl *FD = V.getAsFunctionDecl())
return FD;
return nullptr;
}

void clang::ento::registerThreadModeling(CheckerManager &Mgr) {
Mgr.registerChecker<ThreadModeling>();
}

bool clang::ento::shouldRegisterThreadModeling(const CheckerManager &) {
return true;
}
Loading