diff options
Diffstat (limited to 'include/clang/Analysis/Analyses')
-rw-r--r-- | include/clang/Analysis/Analyses/FormatString.h | 65 | ||||
-rw-r--r-- | include/clang/Analysis/Analyses/ThreadSafety.h | 9 | ||||
-rw-r--r-- | include/clang/Analysis/Analyses/UninitializedValues.h | 60 |
3 files changed, 85 insertions, 49 deletions
diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h index 9ec27ce..7f50ee3 100644 --- a/include/clang/Analysis/Analyses/FormatString.h +++ b/include/clang/Analysis/Analyses/FormatString.h @@ -175,6 +175,7 @@ public: switch (kind) { case PrintErrno: assert(IsPrintf); + return false; case PercentArg: return false; default: @@ -200,7 +201,7 @@ protected: Kind kind; }; -class ArgTypeResult { +class ArgType { public: enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy, AnyCharTy, CStrTy, WCStrTy, WIntTy }; @@ -208,26 +209,26 @@ private: const Kind K; QualType T; const char *Name; - ArgTypeResult(bool) : K(InvalidTy), Name(0) {} + bool Ptr; public: - ArgTypeResult(Kind k = UnknownTy) : K(k), Name(0) {} - ArgTypeResult(Kind k, const char *n) : K(k), Name(n) {} - ArgTypeResult(QualType t) : K(SpecificTy), T(t), Name(0) {} - ArgTypeResult(QualType t, const char *n) : K(SpecificTy), T(t), Name(n) {} - ArgTypeResult(CanQualType t) : K(SpecificTy), T(t), Name(0) {} - - static ArgTypeResult Invalid() { return ArgTypeResult(true); } + ArgType(Kind k = UnknownTy, const char *n = 0) : K(k), Name(n), Ptr(false) {} + ArgType(QualType t, const char *n = 0) + : K(SpecificTy), T(t), Name(n), Ptr(false) {} + ArgType(CanQualType t) : K(SpecificTy), T(t), Name(0), Ptr(false) {} + static ArgType Invalid() { return ArgType(InvalidTy); } bool isValid() const { return K != InvalidTy; } - const QualType *getSpecificType() const { - return K == SpecificTy ? &T : 0; + /// Create an ArgType which corresponds to the type pointer to A. + static ArgType PtrTo(const ArgType& A) { + assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown"); + ArgType Res = A; + Res.Ptr = true; + return Res; } bool matchesType(ASTContext &C, QualType argTy) const; - bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; } - QualType getRepresentativeType(ASTContext &C) const; std::string getRepresentativeTypeName(ASTContext &C) const; @@ -278,7 +279,7 @@ public: return length + UsesDotPrefix; } - ArgTypeResult getArgType(ASTContext &Ctx) const; + ArgType getArgType(ASTContext &Ctx) const; void toString(raw_ostream &os) const; @@ -354,6 +355,10 @@ public: bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const; bool hasStandardLengthConversionCombination() const; + + /// For a TypedefType QT, if it is a named integer type such as size_t, + /// assign the appropriate value to LM and return true. + static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM); }; } // end analyze_format_string namespace @@ -387,7 +392,7 @@ public: } }; -using analyze_format_string::ArgTypeResult; +using analyze_format_string::ArgType; using analyze_format_string::LengthModifier; using analyze_format_string::OptionalAmount; using analyze_format_string::OptionalFlag; @@ -462,7 +467,7 @@ public: /// will return null if the format specifier does not have /// a matching data argument or the matching argument matches /// more than one type. - ArgTypeResult getArgType(ASTContext &Ctx, bool IsObjCLiteral) const; + ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const; const OptionalFlag &hasThousandsGrouping() const { return HasThousandsGrouping; @@ -516,35 +521,11 @@ public: } }; -using analyze_format_string::ArgTypeResult; +using analyze_format_string::ArgType; using analyze_format_string::LengthModifier; using analyze_format_string::OptionalAmount; using analyze_format_string::OptionalFlag; -class ScanfArgTypeResult : public ArgTypeResult { -public: - enum Kind { UnknownTy, InvalidTy, CStrTy, WCStrTy, PtrToArgTypeResultTy }; -private: - Kind K; - ArgTypeResult A; - const char *Name; - QualType getRepresentativeType(ASTContext &C) const; -public: - ScanfArgTypeResult(Kind k = UnknownTy, const char* n = 0) : K(k), Name(n) {} - ScanfArgTypeResult(ArgTypeResult a, const char *n = 0) - : K(PtrToArgTypeResultTy), A(a), Name(n) { - assert(A.isValid()); - } - - static ScanfArgTypeResult Invalid() { return ScanfArgTypeResult(InvalidTy); } - - bool isValid() const { return K != InvalidTy; } - - bool matchesType(ASTContext& C, QualType argTy) const; - - std::string getRepresentativeTypeName(ASTContext& C) const; -}; - class ScanfSpecifier : public analyze_format_string::FormatSpecifier { OptionalFlag SuppressAssignment; // '*' public: @@ -573,7 +554,7 @@ public: return CS.consumesDataArgument() && !SuppressAssignment; } - ScanfArgTypeResult getArgType(ASTContext &Ctx) const; + ArgType getArgType(ASTContext &Ctx) const; bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx); diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h index 26e258d..742cc04 100644 --- a/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/include/clang/Analysis/Analyses/ThreadSafety.h @@ -60,7 +60,8 @@ enum AccessKind { enum LockErrorKind { LEK_LockedSomeLoopIterations, LEK_LockedSomePredecessors, - LEK_LockedAtEndOfFunction + LEK_LockedAtEndOfFunction, + LEK_NotLockedAtEndOfFunction }; /// Handler class for thread safety warnings. @@ -123,11 +124,11 @@ public: /// Warn when a protected operation occurs while the specific mutex protecting /// the operation is not locked. - /// \param LockName -- A StringRef name for the lock expression, to be printed - /// in the error message. /// \param D -- The decl for the protected variable or function /// \param POK -- The kind of protected operation (e.g. variable access) - /// \param AK -- The kind of access (i.e. read or write) that occurred + /// \param LockName -- A StringRef name for the lock expression, to be printed + /// in the error message. + /// \param LK -- The kind of access (i.e. read or write) that occurred /// \param Loc -- The location of the protected operation. virtual void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK, Name LockName, diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h index 4ee6698..45ce4de 100644 --- a/include/clang/Analysis/Analyses/UninitializedValues.h +++ b/include/clang/Analysis/Analyses/UninitializedValues.h @@ -15,6 +15,8 @@ #ifndef LLVM_CLANG_UNINIT_VALS_H #define LLVM_CLANG_UNINIT_VALS_H +#include "llvm/ADT/SmallVector.h" + namespace clang { class AnalysisDeclContext; @@ -23,15 +25,67 @@ class DeclContext; class Expr; class VarDecl; +/// A use of a variable, which might be uninitialized. +class UninitUse { +public: + struct Branch { + const Stmt *Terminator; + unsigned Output; + }; + +private: + /// The expression which uses this variable. + const Expr *User; + + /// Does this use always see an uninitialized value? + bool AlwaysUninit; + + /// This use is always uninitialized if it occurs after any of these branches + /// is taken. + llvm::SmallVector<Branch, 2> UninitBranches; + +public: + UninitUse(const Expr *User, bool AlwaysUninit) : + User(User), AlwaysUninit(AlwaysUninit) {} + + void addUninitBranch(Branch B) { + UninitBranches.push_back(B); + } + + /// Get the expression containing the uninitialized use. + const Expr *getUser() const { return User; } + + /// The kind of uninitialized use. + enum Kind { + /// The use might be uninitialized. + Maybe, + /// The use is uninitialized whenever a certain branch is taken. + Sometimes, + /// The use is always uninitialized. + Always + }; + + /// Get the kind of uninitialized use. + Kind getKind() const { + return AlwaysUninit ? Always : + !branch_empty() ? Sometimes : Maybe; + } + + typedef llvm::SmallVectorImpl<Branch>::const_iterator branch_iterator; + /// Branches which inevitably result in the variable being used uninitialized. + branch_iterator branch_begin() const { return UninitBranches.begin(); } + branch_iterator branch_end() const { return UninitBranches.end(); } + bool branch_empty() const { return UninitBranches.empty(); } +}; + class UninitVariablesHandler { public: UninitVariablesHandler() {} virtual ~UninitVariablesHandler(); /// Called when the uninitialized variable is used at the given expression. - virtual void handleUseOfUninitVariable(const Expr *ex, - const VarDecl *vd, - bool isAlwaysUninit) {} + virtual void handleUseOfUninitVariable(const VarDecl *vd, + const UninitUse &use) {} /// Called when the uninitialized variable analysis detects the /// idiom 'int x = x'. All other uses of 'x' within the initializer |