summaryrefslogtreecommitdiffstats
path: root/include/clang/Analysis/Analyses
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Analysis/Analyses')
-rw-r--r--include/clang/Analysis/Analyses/FormatString.h65
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafety.h9
-rw-r--r--include/clang/Analysis/Analyses/UninitializedValues.h60
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
OpenPOWER on IntegriCloud