@@ -40,28 +40,17 @@ enum class OpenVariant {
4040 OpenAt
4141};
4242
43- static std::optional<int > getCreateFlagValue (const ASTContext &Ctx,
44- const Preprocessor &PP) {
45- std::optional<int > MacroVal = tryExpandAsInteger (" O_CREAT" , PP);
46- if (MacroVal.has_value ())
47- return MacroVal;
48-
49- // If we failed, fall-back to known values.
50- if (Ctx.getTargetInfo ().getTriple ().getVendor () == llvm::Triple::Apple)
51- return {0x0200 };
52- return MacroVal;
53- }
54-
5543namespace {
5644
57- class UnixAPIMisuseChecker : public Checker <check::PreCall> {
45+ class UnixAPIMisuseChecker
46+ : public Checker<check::PreCall, check::ASTDecl<TranslationUnitDecl>> {
5847 const BugType BT_open{this , " Improper use of 'open'" , categories::UnixAPI};
5948 const BugType BT_getline{this , " Improper use of getdelim" ,
6049 categories::UnixAPI};
6150 const BugType BT_pthreadOnce{this , " Improper use of 'pthread_once'" ,
6251 categories::UnixAPI};
6352 const BugType BT_ArgumentNull{this , " NULL pointer" , categories::UnixAPI};
64- const std::optional<int > Val_O_CREAT;
53+ mutable std::optional<uint64_t > Val_O_CREAT;
6554
6655 ProgramStateRef
6756 EnsurePtrNotNull (SVal PtrVal, const Expr *PtrExpr, CheckerContext &C,
@@ -74,9 +63,6 @@ class UnixAPIMisuseChecker : public Checker<check::PreCall> {
7463 const Expr *SizePtrExpr, CheckerContext &C, ProgramStateRef State) const ;
7564
7665public:
77- UnixAPIMisuseChecker (const ASTContext &Ctx, const Preprocessor &PP)
78- : Val_O_CREAT(getCreateFlagValue(Ctx, PP)) {}
79-
8066 void checkASTDecl (const TranslationUnitDecl *TU, AnalysisManager &Mgr,
8167 BugReporter &BR) const ;
8268
@@ -148,6 +134,20 @@ ProgramStateRef UnixAPIMisuseChecker::EnsurePtrNotNull(
148134 return PtrNotNull;
149135}
150136
137+ void UnixAPIMisuseChecker::checkASTDecl (const TranslationUnitDecl *TU,
138+ AnalysisManager &Mgr,
139+ BugReporter &) const {
140+ // The definition of O_CREAT is platform specific.
141+ // Try to get the macro value from the preprocessor.
142+ Val_O_CREAT = tryExpandAsInteger (" O_CREAT" , Mgr.getPreprocessor ());
143+ // If we failed, fall-back to known values.
144+ if (!Val_O_CREAT) {
145+ if (TU->getASTContext ().getTargetInfo ().getTriple ().getVendor () ==
146+ llvm::Triple::Apple)
147+ Val_O_CREAT = 0x0200 ;
148+ }
149+ }
150+
151151// ===----------------------------------------------------------------------===//
152152// "open" (man 2 open)
153153// ===----------------------------------------------------------------------===/
@@ -262,7 +262,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C,
262262 return ;
263263 }
264264
265- if (!Val_O_CREAT. has_value () ) {
265+ if (!Val_O_CREAT) {
266266 return ;
267267 }
268268
@@ -276,7 +276,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C,
276276 }
277277 NonLoc oflags = V.castAs <NonLoc>();
278278 NonLoc ocreateFlag = C.getSValBuilder ()
279- .makeIntVal (Val_O_CREAT. value () , oflagsEx->getType ())
279+ .makeIntVal (* Val_O_CREAT, oflagsEx->getType ())
280280 .castAs <NonLoc>();
281281 SVal maskedFlagsUC = C.getSValBuilder ().evalBinOpNN (state, BO_And,
282282 oflags, ocreateFlag,
@@ -621,17 +621,14 @@ void UnixAPIPortabilityChecker::checkPreStmt(const CallExpr *CE,
621621// Registration.
622622// ===----------------------------------------------------------------------===//
623623
624- void ento::registerUnixAPIMisuseChecker (CheckerManager &Mgr) {
625- Mgr.registerChecker <UnixAPIMisuseChecker>(Mgr.getASTContext (),
626- Mgr.getPreprocessor ());
627- }
628- bool ento::shouldRegisterUnixAPIMisuseChecker (const CheckerManager &Mgr) {
629- return true ;
630- }
624+ #define REGISTER_CHECKER (CHECKERNAME ) \
625+ void ento::register ##CHECKERNAME(CheckerManager &mgr) { \
626+ mgr.registerChecker <CHECKERNAME>(); \
627+ } \
628+ \
629+ bool ento::shouldRegister##CHECKERNAME(const CheckerManager &mgr) { \
630+ return true ; \
631+ }
631632
632- void ento::registerUnixAPIPortabilityChecker (CheckerManager &Mgr) {
633- Mgr.registerChecker <UnixAPIPortabilityChecker>();
634- }
635- bool ento::shouldRegisterUnixAPIPortabilityChecker (const CheckerManager &Mgr) {
636- return true ;
637- }
633+ REGISTER_CHECKER (UnixAPIMisuseChecker)
634+ REGISTER_CHECKER(UnixAPIPortabilityChecker)
0 commit comments