aboutsummaryrefslogtreecommitdiff
path: root/include/clang/Analysis
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Analysis')
-rw-r--r--include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h4
-rw-r--r--include/clang/Analysis/Analyses/Consumed.h60
-rw-r--r--include/clang/Analysis/Analyses/Dominators.h2
-rw-r--r--include/clang/Analysis/Analyses/FormatString.h2
-rw-r--r--include/clang/Analysis/Analyses/LiveVariables.h34
-rw-r--r--include/clang/Analysis/Analyses/ReachableCode.h2
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyCommon.h2
-rw-r--r--include/clang/Analysis/AnalysisDeclContext.h12
-rw-r--r--include/clang/Analysis/CFG.h144
-rw-r--r--include/clang/Analysis/CFGStmtMap.h8
-rw-r--r--include/clang/Analysis/CloneDetection.h2
-rw-r--r--include/clang/Analysis/ConstructionContext.h265
-rw-r--r--include/clang/Analysis/DomainSpecific/CocoaConventions.h10
-rw-r--r--include/clang/Analysis/DomainSpecific/ObjCNoReturn.h4
-rw-r--r--include/clang/Analysis/ProgramPoint.h28
-rw-r--r--include/clang/Analysis/Support/BumpVector.h52
16 files changed, 404 insertions, 227 deletions
diff --git a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
index da59514c4fa6..49da6815ace9 100644
--- a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
+++ b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
@@ -23,7 +23,7 @@ namespace clang {
class CFG;
class CFGBlock;
-
+
// A class that performs reachability queries for CFGBlocks. Several internal
// checks in this checker require reachability information. The requests all
// tend to have a common destination, so we lazily do a predecessor search
@@ -45,7 +45,7 @@ public:
private:
void mapReachability(const CFGBlock *Dst);
};
-
+
} // namespace clang
#endif // LLVM_CLANG_ANALYSIS_ANALYSES_CFGREACHABILITYANALYSIS_H
diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h
index 6003d665fd88..5a70989e5087 100644
--- a/include/clang/Analysis/Analyses/Consumed.h
+++ b/include/clang/Analysis/Analyses/Consumed.h
@@ -38,18 +38,18 @@ class Stmt;
class VarDecl;
namespace consumed {
-
+
class ConsumedStmtVisitor;
enum ConsumedState {
// No state information for the given variable.
CS_None,
-
+
CS_Unknown,
CS_Unconsumed,
CS_Consumed
};
-
+
using OptionalNotes = SmallVector<PartialDiagnosticAt, 1>;
using DelayedDiag = std::pair<PartialDiagnosticAt, OptionalNotes>;
using DiagList = std::list<DelayedDiag>;
@@ -60,7 +60,7 @@ namespace consumed {
/// Emit the warnings and notes left by the analysis.
virtual void emitDiagnostics() {}
-
+
/// Warn that a variable's state doesn't match at the entry and exit
/// of a loop.
///
@@ -70,7 +70,7 @@ namespace consumed {
/// state.
virtual void warnLoopStateMismatch(SourceLocation Loc,
StringRef VariableName) {}
-
+
/// Warn about parameter typestate mismatches upon return.
///
/// \param Loc -- The SourceLocation of the return statement.
@@ -84,22 +84,22 @@ namespace consumed {
StringRef VariableName,
StringRef ExpectedState,
StringRef ObservedState) {}
-
+
// FIXME: Add documentation.
virtual void warnParamTypestateMismatch(SourceLocation LOC,
StringRef ExpectedState,
StringRef ObservedState) {}
-
+
// FIXME: This can be removed when the attr propagation fix for templated
// classes lands.
/// Warn about return typestates set for unconsumable types.
- ///
+ ///
/// \param Loc -- The location of the attributes.
///
/// \param TypeName -- The name of the unconsumable type.
virtual void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
StringRef TypeName) {}
-
+
/// Warn about return typestate mismatches.
///
/// \param Loc -- The SourceLocation of the return statement.
@@ -144,71 +144,71 @@ namespace consumed {
using VarMapType = llvm::DenseMap<const VarDecl *, ConsumedState>;
using TmpMapType =
llvm::DenseMap<const CXXBindTemporaryExpr *, ConsumedState>;
-
+
protected:
bool Reachable = true;
const Stmt *From = nullptr;
VarMapType VarMap;
TmpMapType TmpMap;
-
+
public:
ConsumedStateMap() = default;
ConsumedStateMap(const ConsumedStateMap &Other)
: Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap),
TmpMap() {}
-
+
/// Warn if any of the parameters being tracked are not in the state
/// they were declared to be in upon return from a function.
void checkParamsForReturnTypestate(SourceLocation BlameLoc,
ConsumedWarningsHandlerBase &WarningsHandler) const;
-
+
/// Clear the TmpMap.
void clearTemporaries();
-
+
/// Get the consumed state of a given variable.
ConsumedState getState(const VarDecl *Var) const;
-
+
/// Get the consumed state of a given temporary value.
ConsumedState getState(const CXXBindTemporaryExpr *Tmp) const;
-
+
/// Merge this state map with another map.
void intersect(const ConsumedStateMap &Other);
void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack,
const ConsumedStateMap *LoopBackStates,
ConsumedWarningsHandlerBase &WarningsHandler);
-
+
/// Return true if this block is reachable.
bool isReachable() const { return Reachable; }
-
+
/// Mark the block as unreachable.
void markUnreachable();
-
+
/// Set the source for a decision about the branching of states.
/// \param Source -- The statement that was the origin of a branching
/// decision.
void setSource(const Stmt *Source) { this->From = Source; }
-
+
/// Set the consumed state of a given variable.
void setState(const VarDecl *Var, ConsumedState State);
-
+
/// Set the consumed state of a given temporary value.
void setState(const CXXBindTemporaryExpr *Tmp, ConsumedState State);
-
+
/// Remove the temporary value from our state map.
void remove(const CXXBindTemporaryExpr *Tmp);
-
+
/// Tests to see if there is a mismatch in the states stored in two
/// maps.
///
/// \param Other -- The second map to compare against.
bool operator!=(const ConsumedStateMap *Other) const;
};
-
+
class ConsumedBlockInfo {
std::vector<std::unique_ptr<ConsumedStateMap>> StateMapsArray;
std::vector<unsigned int> VisitOrder;
-
+
public:
ConsumedBlockInfo() = default;
@@ -218,7 +218,7 @@ namespace consumed {
for (const auto BI : *SortedGraph)
VisitOrder[BI->getBlockID()] = VisitOrderCounter++;
}
-
+
bool allBackEdgesVisited(const CFGBlock *CurrBlock,
const CFGBlock *TargetBlock);
@@ -228,7 +228,7 @@ namespace consumed {
std::unique_ptr<ConsumedStateMap> StateMap);
ConsumedStateMap* borrowInfo(const CFGBlock *Block);
-
+
void discardInfo(const CFGBlock *Block);
std::unique_ptr<ConsumedStateMap> getInfo(const CFGBlock *Block);
@@ -243,12 +243,12 @@ namespace consumed {
std::unique_ptr<ConsumedStateMap> CurrStates;
ConsumedState ExpectedReturnState;
-
+
void determineExpectedReturnState(AnalysisDeclContext &AC,
const FunctionDecl *D);
bool splitState(const CFGBlock *CurrBlock,
const ConsumedStmtVisitor &Visitor);
-
+
public:
ConsumedWarningsHandlerBase &WarningsHandler;
@@ -256,7 +256,7 @@ namespace consumed {
: WarningsHandler(WarningsHandler) {}
ConsumedState getExpectedReturnState() const { return ExpectedReturnState; }
-
+
/// Check a function's CFG for consumed violations.
///
/// We traverse the blocks in the CFG, keeping track of the state of each
diff --git a/include/clang/Analysis/Analyses/Dominators.h b/include/clang/Analysis/Analyses/Dominators.h
index a9cdc5560bc0..021e98dcd885 100644
--- a/include/clang/Analysis/Analyses/Dominators.h
+++ b/include/clang/Analysis/Analyses/Dominators.h
@@ -20,7 +20,7 @@
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Support/GenericDomTree.h"
-#include "llvm/Support/GenericDomTreeConstruction.h"
+#include "llvm/Support/GenericDomTreeConstruction.h"
#include "llvm/Support/raw_ostream.h"
// FIXME: There is no good reason for the domtree to require a print method
diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h
index 6f8bb9b4095f..598d341ac829 100644
--- a/include/clang/Analysis/Analyses/FormatString.h
+++ b/include/clang/Analysis/Analyses/FormatString.h
@@ -236,7 +236,7 @@ public:
const char *toString() const;
bool isPrintfKind() const { return IsPrintf; }
-
+
Optional<ConversionSpecifier> getStandardSpecifier() const;
protected:
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h
index 21c3ba255c36..0cb500fffb95 100644
--- a/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/include/clang/Analysis/Analyses/LiveVariables.h
@@ -25,7 +25,7 @@ class CFGBlock;
class Stmt;
class DeclRefExpr;
class SourceManager;
-
+
class LiveVariables : public ManagedAnalysis {
public:
class LivenessValues {
@@ -34,7 +34,7 @@ public:
llvm::ImmutableSet<const Stmt *> liveStmts;
llvm::ImmutableSet<const VarDecl *> liveDecls;
llvm::ImmutableSet<const BindingDecl *> liveBindings;
-
+
bool equals(const LivenessValues &V) const;
LivenessValues()
@@ -48,21 +48,21 @@ public:
bool isLive(const Stmt *S) const;
bool isLive(const VarDecl *D) const;
-
- friend class LiveVariables;
+
+ friend class LiveVariables;
};
-
+
class Observer {
virtual void anchor();
public:
virtual ~Observer() {}
-
+
/// A callback invoked right before invoking the
/// liveness transfer function on the given statement.
virtual void observeStmt(const Stmt *S,
const CFGBlock *currentBlock,
const LivenessValues& V) {}
-
+
/// Called when the live variables analysis registers
/// that a variable is killed.
virtual void observerKill(const DeclRefExpr *DR) {}
@@ -73,47 +73,47 @@ public:
/// Compute the liveness information for a given CFG.
static LiveVariables *computeLiveness(AnalysisDeclContext &analysisContext,
bool killAtAssign);
-
+
/// Return true if a variable is live at the end of a
/// specified block.
bool isLive(const CFGBlock *B, const VarDecl *D);
-
+
/// Returns true if a variable is live at the beginning of the
/// the statement. This query only works if liveness information
/// has been recorded at the statement level (see runOnAllBlocks), and
/// only returns liveness information for block-level expressions.
bool isLive(const Stmt *S, const VarDecl *D);
-
+
/// Returns true the block-level expression "value" is live
/// before the given block-level expression (see runOnAllBlocks).
bool isLive(const Stmt *Loc, const Stmt *StmtVal);
-
+
/// Print to stderr the liveness information associated with
/// each basic block.
void dumpBlockLiveness(const SourceManager& M);
void runOnAllBlocks(Observer &obs);
-
+
static LiveVariables *create(AnalysisDeclContext &analysisContext) {
return computeLiveness(analysisContext, true);
}
-
+
static const void *getTag();
-
+
private:
LiveVariables(void *impl);
void *impl;
};
-
+
class RelaxedLiveVariables : public LiveVariables {
public:
static LiveVariables *create(AnalysisDeclContext &analysisContext) {
return computeLiveness(analysisContext, false);
}
-
+
static const void *getTag();
};
-
+
} // end namespace clang
#endif
diff --git a/include/clang/Analysis/Analyses/ReachableCode.h b/include/clang/Analysis/Analyses/ReachableCode.h
index 4c523bfc8b56..d79f1b03df7b 100644
--- a/include/clang/Analysis/Analyses/ReachableCode.h
+++ b/include/clang/Analysis/Analyses/ReachableCode.h
@@ -57,7 +57,7 @@ public:
};
/// ScanReachableFromBlock - Mark all blocks reachable from Start.
-/// Returns the total number of blocks that were marked reachable.
+/// Returns the total number of blocks that were marked reachable.
unsigned ScanReachableFromBlock(const CFGBlock *Start,
llvm::BitVector &Reachable);
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
index 580872e17ef4..599c164923cb 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -500,7 +500,7 @@ private:
std::vector<til::BasicBlock *> BlockMap;
// Extra information per BB. Indexed by clang BlockID.
- std::vector<BlockInfo> BBInfo;
+ std::vector<BlockInfo> BBInfo;
LVarDefinitionMap CurrentLVarMap;
std::vector<til::Phi *> CurrentArguments;
diff --git a/include/clang/Analysis/AnalysisDeclContext.h b/include/clang/Analysis/AnalysisDeclContext.h
index 8c391b5ee1e5..19531d92e645 100644
--- a/include/clang/Analysis/AnalysisDeclContext.h
+++ b/include/clang/Analysis/AnalysisDeclContext.h
@@ -111,7 +111,7 @@ public:
AnalysisDeclContextManager *getManager() const {
return Manager;
}
-
+
/// Return the build options used to construct the CFG.
CFG::BuildOptions &getCFGBuildOptions() {
return cfgBuildOptions;
@@ -190,7 +190,7 @@ public:
const Stmt *S,
const CFGBlock *Blk,
unsigned Idx);
-
+
const BlockInvocationContext *
getBlockInvocationContext(const LocationContext *parent,
const BlockDecl *BD,
@@ -359,7 +359,7 @@ class BlockInvocationContext : public LocationContext {
friend class LocationContextManager;
const BlockDecl *BD;
-
+
// FIXME: Come up with a more type-safe way to model context-sensitivity.
const void *ContextData;
@@ -372,7 +372,7 @@ public:
~BlockInvocationContext() override = default;
const BlockDecl *getBlockDecl() const { return BD; }
-
+
const void *getContextData() const { return ContextData; }
void Profile(llvm::FoldingSetNodeID &ID) override;
@@ -403,7 +403,7 @@ public:
const ScopeContext *getScope(AnalysisDeclContext *ctx,
const LocationContext *parent,
const Stmt *s);
-
+
const BlockInvocationContext *
getBlockInvocationContext(AnalysisDeclContext *ctx,
const LocationContext *parent,
@@ -463,7 +463,7 @@ public:
CFG::BuildOptions &getCFGBuildOptions() {
return cfgBuildOptions;
}
-
+
/// Return true if faux bodies should be synthesized for well-known
/// functions.
bool synthesizeBodies() const { return SynthesizeBodies; }
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index f25789822d16..bf81d8358a54 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -15,9 +15,10 @@
#ifndef LLVM_CLANG_ANALYSIS_CFG_H
#define LLVM_CLANG_ANALYSIS_CFG_H
-#include "clang/AST/ExprCXX.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "clang/Analysis/ConstructionContext.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
@@ -51,7 +52,7 @@ class FieldDecl;
class LangOptions;
class VarDecl;
-/// CFGElement - Represents a top-level expression in a basic block.
+/// Represents a top-level expression in a basic block.
class CFGElement {
public:
enum Kind {
@@ -144,9 +145,9 @@ protected:
CFGStmt() = default;
};
-/// CFGConstructor - Represents C++ constructor call. Maintains information
-/// necessary to figure out what memory is being initialized by the
-/// constructor expression. For now this is only used by the analyzer's CFG.
+/// Represents C++ constructor call. Maintains information necessary to figure
+/// out what memory is being initialized by the constructor expression. For now
+/// this is only used by the analyzer's CFG.
class CFGConstructor : public CFGStmt {
public:
explicit CFGConstructor(CXXConstructExpr *CE, const ConstructionContext *C)
@@ -169,30 +170,34 @@ private:
}
};
-/// CFGCXXRecordTypedCall - Represents a function call that returns a C++ object
-/// by value. This, like constructor, requires a construction context in order
-/// to understand the storage of the returned object . In C such tracking is not
-/// necessary because no additional effort is required for destroying the object
-/// or modeling copy elision. Like CFGConstructor, this element is for now only
-/// used by the analyzer's CFG.
+/// Represents a function call that returns a C++ object by value. This, like
+/// constructor, requires a construction context in order to understand the
+/// storage of the returned object . In C such tracking is not necessary because
+/// no additional effort is required for destroying the object or modeling copy
+/// elision. Like CFGConstructor, this element is for now only used by the
+/// analyzer's CFG.
class CFGCXXRecordTypedCall : public CFGStmt {
public:
/// Returns true when call expression \p CE needs to be represented
/// by CFGCXXRecordTypedCall, as opposed to a regular CFGStmt.
- static bool isCXXRecordTypedCall(CallExpr *CE, const ASTContext &ACtx) {
- return CE->getCallReturnType(ACtx).getCanonicalType()->getAsCXXRecordDecl();
+ static bool isCXXRecordTypedCall(Expr *E) {
+ assert(isa<CallExpr>(E) || isa<ObjCMessageExpr>(E));
+ // There is no such thing as reference-type expression. If the function
+ // returns a reference, it'll return the respective lvalue or xvalue
+ // instead, and we're only interested in objects.
+ return !E->isGLValue() &&
+ E->getType().getCanonicalType()->getAsCXXRecordDecl();
}
- explicit CFGCXXRecordTypedCall(CallExpr *CE, const ConstructionContext *C)
- : CFGStmt(CE, CXXRecordTypedCall) {
- // FIXME: This is not protected against squeezing a non-record-typed-call
- // into the constructor. An assertion would require passing an ASTContext
- // which would mean paying for something we don't use.
+ explicit CFGCXXRecordTypedCall(Expr *E, const ConstructionContext *C)
+ : CFGStmt(E, CXXRecordTypedCall) {
+ assert(isCXXRecordTypedCall(E));
assert(C && (isa<TemporaryObjectConstructionContext>(C) ||
// These are possible in C++17 due to mandatory copy elision.
isa<ReturnedValueConstructionContext>(C) ||
isa<VariableConstructionContext>(C) ||
- isa<ConstructorInitializerConstructionContext>(C)));
+ isa<ConstructorInitializerConstructionContext>(C) ||
+ isa<ArgumentConstructionContext>(C)));
Data2.setPointer(const_cast<ConstructionContext *>(C));
}
@@ -210,8 +215,8 @@ private:
}
};
-/// CFGInitializer - Represents C++ base or member initializer from
-/// constructor's initialization list.
+/// Represents C++ base or member initializer from constructor's initialization
+/// list.
class CFGInitializer : public CFGElement {
public:
explicit CFGInitializer(CXXCtorInitializer *initializer)
@@ -231,7 +236,7 @@ private:
}
};
-/// CFGNewAllocator - Represents C++ allocator call.
+/// Represents C++ allocator call.
class CFGNewAllocator : public CFGElement {
public:
explicit CFGNewAllocator(const CXXNewExpr *S)
@@ -349,8 +354,8 @@ private:
}
};
-/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
-/// by compiler on various occasions.
+/// Represents C++ object destructor implicitly generated by compiler on various
+/// occasions.
class CFGImplicitDtor : public CFGElement {
protected:
CFGImplicitDtor() = default;
@@ -373,9 +378,9 @@ private:
}
};
-/// CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated
-/// for automatic object or temporary bound to const reference at the point
-/// of leaving its local scope.
+/// Represents C++ object destructor implicitly generated for automatic object
+/// or temporary bound to const reference at the point of leaving its local
+/// scope.
class CFGAutomaticObjDtor: public CFGImplicitDtor {
public:
CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt)
@@ -400,8 +405,7 @@ private:
}
};
-/// CFGDeleteDtor - Represents C++ object destructor generated
-/// from a call to delete.
+/// Represents C++ object destructor generated from a call to delete.
class CFGDeleteDtor : public CFGImplicitDtor {
public:
CFGDeleteDtor(const CXXRecordDecl *RD, const CXXDeleteExpr *DE)
@@ -426,8 +430,8 @@ private:
}
};
-/// CFGBaseDtor - Represents C++ object destructor implicitly generated for
-/// base object in destructor.
+/// Represents C++ object destructor implicitly generated for base object in
+/// destructor.
class CFGBaseDtor : public CFGImplicitDtor {
public:
CFGBaseDtor(const CXXBaseSpecifier *base)
@@ -447,8 +451,8 @@ private:
}
};
-/// CFGMemberDtor - Represents C++ object destructor implicitly generated for
-/// member object in destructor.
+/// Represents C++ object destructor implicitly generated for member object in
+/// destructor.
class CFGMemberDtor : public CFGImplicitDtor {
public:
CFGMemberDtor(const FieldDecl *field)
@@ -468,8 +472,8 @@ private:
}
};
-/// CFGTemporaryDtor - Represents C++ object destructor implicitly generated
-/// at the end of full expression for temporary object.
+/// Represents C++ object destructor implicitly generated at the end of full
+/// expression for temporary object.
class CFGTemporaryDtor : public CFGImplicitDtor {
public:
CFGTemporaryDtor(CXXBindTemporaryExpr *expr)
@@ -489,7 +493,7 @@ private:
}
};
-/// CFGTerminator - Represents CFGBlock terminator statement.
+/// Represents CFGBlock terminator statement.
///
/// TemporaryDtorsBranch bit is set to true if the terminator marks a branch
/// in control flow of destructors of temporaries. In this case terminator
@@ -520,7 +524,7 @@ public:
explicit operator bool() const { return getStmt(); }
};
-/// CFGBlock - Represents a single basic block in a source-level CFG.
+/// Represents a single basic block in a source-level CFG.
/// It consists of:
///
/// (1) A set of statements/expressions (which may contain subexpressions).
@@ -588,26 +592,24 @@ class CFGBlock {
bool empty() const { return Impl.empty(); }
};
- /// Stmts - The set of statements in the basic block.
+ /// The set of statements in the basic block.
ElementList Elements;
- /// Label - An (optional) label that prefixes the executable
- /// statements in the block. When this variable is non-NULL, it is
- /// either an instance of LabelStmt, SwitchCase or CXXCatchStmt.
+ /// An (optional) label that prefixes the executable statements in the block.
+ /// When this variable is non-NULL, it is either an instance of LabelStmt,
+ /// SwitchCase or CXXCatchStmt.
Stmt *Label = nullptr;
- /// Terminator - The terminator for a basic block that
- /// indicates the type of control-flow that occurs between a block
- /// and its successors.
+ /// The terminator for a basic block that indicates the type of control-flow
+ /// that occurs between a block and its successors.
CFGTerminator Terminator;
- /// LoopTarget - Some blocks are used to represent the "loop edge" to
- /// the start of a loop from within the loop body. This Stmt* will be
- /// refer to the loop statement for such blocks (and be null otherwise).
+ /// Some blocks are used to represent the "loop edge" to the start of a loop
+ /// from within the loop body. This Stmt* will be refer to the loop statement
+ /// for such blocks (and be null otherwise).
const Stmt *LoopTarget = nullptr;
- /// BlockID - A numerical ID assigned to a CFGBlock during construction
- /// of the CFG.
+ /// A numerical ID assigned to a CFGBlock during construction of the CFG.
unsigned BlockID;
public:
@@ -629,7 +631,7 @@ public:
public:
/// Construct an AdjacentBlock with a possibly unreachable block.
AdjacentBlock(CFGBlock *B, bool IsReachable);
-
+
/// Construct an AdjacentBlock with a reachable block and an alternate
/// unreachable block.
AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock);
@@ -665,13 +667,12 @@ public:
};
private:
- /// Predecessors/Successors - Keep track of the predecessor / successor
- /// CFG blocks.
+ /// Keep track of the predecessor / successor CFG blocks.
using AdjacentBlocks = BumpVector<AdjacentBlock>;
AdjacentBlocks Preds;
AdjacentBlocks Succs;
- /// NoReturn - This bit is set when the basic block contains a function call
+ /// This bit is set when the basic block contains a function call
/// or implicit destructor that is attributed as 'noreturn'. In that case,
/// control cannot technically ever proceed past this block. All such blocks
/// will have a single immediate successor: the exit block. This allows them
@@ -682,7 +683,7 @@ private:
/// storage if the memory usage of CFGBlock becomes an issue.
unsigned HasNoReturnElement : 1;
- /// Parent - The parent CFG that owns this CFGBlock.
+ /// The parent CFG that owns this CFGBlock.
CFG *Parent;
public:
@@ -878,10 +879,10 @@ public:
Elements.push_back(CFGConstructor(CE, CC), C);
}
- void appendCXXRecordTypedCall(CallExpr *CE,
+ void appendCXXRecordTypedCall(Expr *E,
const ConstructionContext *CC,
BumpVectorContext &C) {
- Elements.push_back(CFGCXXRecordTypedCall(CE, CC), C);
+ Elements.push_back(CFGCXXRecordTypedCall(E, CC), C);
}
void appendInitializer(CXXCtorInitializer *initializer,
@@ -992,7 +993,7 @@ public:
bool isAlwaysTrue) {}
};
-/// CFG - Represents a source-level, intra-procedural CFG that represents the
+/// Represents a source-level, intra-procedural CFG that represents the
/// control-flow of a Stmt. The Stmt can represent an entire function body,
/// or a single expression. A CFG will always contain one empty block that
/// represents the Exit point of the CFG. A CFG will also contain a designated
@@ -1044,21 +1045,21 @@ public:
}
};
- /// buildCFG - Builds a CFG from an AST.
+ /// Builds a CFG from an AST.
static std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *AST, ASTContext *C,
const BuildOptions &BO);
- /// createBlock - Create a new block in the CFG. The CFG owns the block;
- /// the caller should not directly free it.
+ /// Create a new block in the CFG. The CFG owns the block; the caller should
+ /// not directly free it.
CFGBlock *createBlock();
- /// setEntry - Set the entry block of the CFG. This is typically used
- /// only during CFG construction. Most CFG clients expect that the
- /// entry block has no predecessors and contains no statements.
+ /// Set the entry block of the CFG. This is typically used only during CFG
+ /// construction. Most CFG clients expect that the entry block has no
+ /// predecessors and contains no statements.
void setEntry(CFGBlock *B) { Entry = B; }
- /// setIndirectGotoBlock - Set the block used for indirect goto jumps.
- /// This is typically used only during CFG construction.
+ /// Set the block used for indirect goto jumps. This is typically used only
+ /// during CFG construction.
void setIndirectGotoBlock(CFGBlock *B) { IndirectGotoBlock = B; }
//===--------------------------------------------------------------------===//
@@ -1152,8 +1153,8 @@ public:
template <typename CALLBACK>
void VisitBlockStmts(CALLBACK& O) const {
- for (const_iterator I=begin(), E=end(); I != E; ++I)
- for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end();
+ for (const_iterator I = begin(), E = end(); I != E; ++I)
+ for (CFGBlock::const_iterator BI = (*I)->begin(), BE = (*I)->end();
BI != BE; ++BI) {
if (Optional<CFGStmt> stmt = BI->getAs<CFGStmt>())
O(const_cast<Stmt*>(stmt->getStmt()));
@@ -1164,13 +1165,12 @@ public:
// CFG Introspection.
//===--------------------------------------------------------------------===//
- /// getNumBlockIDs - Returns the total number of BlockIDs allocated (which
- /// start at 0).
+ /// Returns the total number of BlockIDs allocated (which start at 0).
unsigned getNumBlockIDs() const { return NumBlockIDs; }
- /// size - Return the total number of CFGBlocks within the CFG
- /// This is simply a renaming of the getNumBlockIDs(). This is necessary
- /// because the dominator implementation needs such an interface.
+ /// Return the total number of CFGBlocks within the CFG This is simply a
+ /// renaming of the getNumBlockIDs(). This is necessary because the dominator
+ /// implementation needs such an interface.
unsigned size() const { return NumBlockIDs; }
//===--------------------------------------------------------------------===//
diff --git a/include/clang/Analysis/CFGStmtMap.h b/include/clang/Analysis/CFGStmtMap.h
index 4dfa91df0f42..78e637daf379 100644
--- a/include/clang/Analysis/CFGStmtMap.h
+++ b/include/clang/Analysis/CFGStmtMap.h
@@ -19,20 +19,18 @@
namespace clang {
-class CFG;
-class CFGBlock;
class ParentMap;
class Stmt;
class CFGStmtMap {
ParentMap *PM;
void *M;
-
+
CFGStmtMap(ParentMap *pm, void *m) : PM(pm), M(m) {}
-
+
public:
~CFGStmtMap();
-
+
/// Returns a new CFGMap for the given CFG. It is the caller's
/// responsibility to 'delete' this object when done using it.
static CFGStmtMap *Build(CFG* C, ParentMap *PM);
diff --git a/include/clang/Analysis/CloneDetection.h b/include/clang/Analysis/CloneDetection.h
index 955777a11a65..915ec58a5144 100644
--- a/include/clang/Analysis/CloneDetection.h
+++ b/include/clang/Analysis/CloneDetection.h
@@ -332,7 +332,7 @@ struct FilenamePatternConstraint {
StringRef IgnoredFilesPattern;
std::shared_ptr<llvm::Regex> IgnoredFilesRegex;
- FilenamePatternConstraint(StringRef IgnoredFilesPattern)
+ FilenamePatternConstraint(StringRef IgnoredFilesPattern)
: IgnoredFilesPattern(IgnoredFilesPattern) {
IgnoredFilesRegex = std::make_shared<llvm::Regex>("^(" +
IgnoredFilesPattern.str() + "$)");
diff --git a/include/clang/Analysis/ConstructionContext.h b/include/clang/Analysis/ConstructionContext.h
index 40cb0e7e5dda..aee67865df25 100644
--- a/include/clang/Analysis/ConstructionContext.h
+++ b/include/clang/Analysis/ConstructionContext.h
@@ -22,66 +22,201 @@
namespace clang {
-/// Construction context is a linked list of multiple layers. Layers are
-/// created gradually while traversing the AST, and layers that represent
-/// the outmost AST nodes are built first, while the node that immediately
-/// contains the constructor would be built last and capture the previous
-/// layers as its parents. Construction context captures the last layer
-/// (which has links to the previous layers) and classifies the seemingly
-/// arbitrary chain of layers into one of the possible ways of constructing
-/// an object in C++ for user-friendly experience.
-class ConstructionContextLayer {
+/// Represents a single point (AST node) in the program that requires attention
+/// during construction of an object. ConstructionContext would be represented
+/// as a list of such items.
+class ConstructionContextItem {
public:
- typedef llvm::PointerUnion<Stmt *, CXXCtorInitializer *> TriggerTy;
+ enum ItemKind {
+ VariableKind,
+ NewAllocatorKind,
+ ReturnKind,
+ MaterializationKind,
+ TemporaryDestructorKind,
+ ElidedDestructorKind,
+ ElidableConstructorKind,
+ ArgumentKind,
+ STATEMENT_WITH_INDEX_KIND_BEGIN=ArgumentKind,
+ STATEMENT_WITH_INDEX_KIND_END=ArgumentKind,
+ STATEMENT_KIND_BEGIN = VariableKind,
+ STATEMENT_KIND_END = ArgumentKind,
+ InitializerKind,
+ INITIALIZER_KIND_BEGIN=InitializerKind,
+ INITIALIZER_KIND_END=InitializerKind
+ };
+
+ LLVM_DUMP_METHOD static StringRef getKindAsString(ItemKind K) {
+ switch (K) {
+ case VariableKind: return "construct into local variable";
+ case NewAllocatorKind: return "construct into new-allocator";
+ case ReturnKind: return "construct into return address";
+ case MaterializationKind: return "materialize temporary";
+ case TemporaryDestructorKind: return "destroy temporary";
+ case ElidedDestructorKind: return "elide destructor";
+ case ElidableConstructorKind: return "elide constructor";
+ case ArgumentKind: return "construct into argument";
+ case InitializerKind: return "construct into member variable";
+ };
+ llvm_unreachable("Unknown ItemKind");
+ }
private:
+ const void *const Data;
+ const ItemKind Kind;
+ const unsigned Index = 0;
+
+ bool hasStatement() const {
+ return Kind >= STATEMENT_KIND_BEGIN &&
+ Kind <= STATEMENT_KIND_END;
+ }
+
+ bool hasIndex() const {
+ return Kind >= STATEMENT_WITH_INDEX_KIND_BEGIN &&
+ Kind >= STATEMENT_WITH_INDEX_KIND_END;
+ }
+
+ bool hasInitializer() const {
+ return Kind >= INITIALIZER_KIND_BEGIN &&
+ Kind <= INITIALIZER_KIND_END;
+ }
+
+public:
+ // ConstructionContextItem should be simple enough so that it was easy to
+ // re-construct it from the AST node it captures. For that reason we provide
+ // simple implicit conversions from all sorts of supported AST nodes.
+ ConstructionContextItem(const DeclStmt *DS)
+ : Data(DS), Kind(VariableKind) {}
+
+ ConstructionContextItem(const CXXNewExpr *NE)
+ : Data(NE), Kind(NewAllocatorKind) {}
+
+ ConstructionContextItem(const ReturnStmt *RS)
+ : Data(RS), Kind(ReturnKind) {}
+
+ ConstructionContextItem(const MaterializeTemporaryExpr *MTE)
+ : Data(MTE), Kind(MaterializationKind) {}
+
+ ConstructionContextItem(const CXXBindTemporaryExpr *BTE,
+ bool IsElided = false)
+ : Data(BTE),
+ Kind(IsElided ? ElidedDestructorKind : TemporaryDestructorKind) {}
+
+ ConstructionContextItem(const CXXConstructExpr *CE)
+ : Data(CE), Kind(ElidableConstructorKind) {}
+
+ ConstructionContextItem(const CallExpr *CE, unsigned Index)
+ : Data(CE), Kind(ArgumentKind), Index(Index) {}
+
+ ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index)
+ : Data(CE), Kind(ArgumentKind), Index(Index) {}
+
+ ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index)
+ : Data(ME), Kind(ArgumentKind), Index(Index) {}
+
+ // A polymorphic version of the previous calls with dynamic type check.
+ ConstructionContextItem(const Expr *E, unsigned Index)
+ : Data(E), Kind(ArgumentKind), Index(Index) {
+ assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) ||
+ isa<ObjCMessageExpr>(E));
+ }
+
+ ConstructionContextItem(const CXXCtorInitializer *Init)
+ : Data(Init), Kind(InitializerKind), Index(0) {}
+
+ ItemKind getKind() const { return Kind; }
+
+ LLVM_DUMP_METHOD StringRef getKindAsString() const {
+ return getKindAsString(getKind());
+ }
+
/// The construction site - the statement that triggered the construction
/// for one of its parts. For instance, stack variable declaration statement
/// triggers construction of itself or its elements if it's an array,
/// new-expression triggers construction of the newly allocated object(s).
- TriggerTy Trigger;
+ const Stmt *getStmt() const {
+ assert(hasStatement());
+ return static_cast<const Stmt *>(Data);
+ }
+
+ const Stmt *getStmtOrNull() const {
+ return hasStatement() ? getStmt() : nullptr;
+ }
+
+ /// The construction site is not necessarily a statement. It may also be a
+ /// CXXCtorInitializer, which means that a member variable is being
+ /// constructed during initialization of the object that contains it.
+ const CXXCtorInitializer *getCXXCtorInitializer() const {
+ assert(hasInitializer());
+ return static_cast<const CXXCtorInitializer *>(Data);
+ }
- /// Sometimes a single trigger is not enough to describe the construction
- /// site. In this case we'd have a chain of "partial" construction context
- /// layers.
- /// Some examples:
- /// - A constructor within in an aggregate initializer list within a variable
- /// would have a construction context of the initializer list with
- /// the parent construction context of a variable.
- /// - A constructor for a temporary that needs to be both destroyed
- /// and materialized into an elidable copy constructor would have a
- /// construction context of a CXXBindTemporaryExpr with the parent
- /// construction context of a MaterializeTemproraryExpr.
- /// Not all of these are currently supported.
+ /// If a single trigger statement triggers multiple constructors, they are
+ /// usually being enumerated. This covers function argument constructors
+ /// triggered by a call-expression and items in an initializer list triggered
+ /// by an init-list-expression.
+ unsigned getIndex() const {
+ // This is a fairly specific request. Let's make sure the user knows
+ // what he's doing.
+ assert(hasIndex());
+ return Index;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddPointer(Data);
+ ID.AddInteger(Kind);
+ ID.AddInteger(Index);
+ }
+
+ bool operator==(const ConstructionContextItem &Other) const {
+ // For most kinds the Index comparison is trivially true, but
+ // checking kind separately doesn't seem to be less expensive
+ // than checking Index. Same in operator<().
+ return std::make_tuple(Data, Kind, Index) ==
+ std::make_tuple(Other.Data, Other.Kind, Other.Index);
+ }
+
+ bool operator<(const ConstructionContextItem &Other) const {
+ return std::make_tuple(Data, Kind, Index) <
+ std::make_tuple(Other.Data, Other.Kind, Other.Index);
+ }
+};
+
+/// Construction context can be seen as a linked list of multiple layers.
+/// Sometimes a single trigger is not enough to describe the construction
+/// site. That's what causing us to have a chain of "partial" construction
+/// context layers. Some examples:
+/// - A constructor within in an aggregate initializer list within a variable
+/// would have a construction context of the initializer list with
+/// the parent construction context of a variable.
+/// - A constructor for a temporary that needs to be both destroyed
+/// and materialized into an elidable copy constructor would have a
+/// construction context of a CXXBindTemporaryExpr with the parent
+/// construction context of a MaterializeTemproraryExpr.
+/// Not all of these are currently supported.
+/// Layers are created gradually while traversing the AST, and layers that
+/// represent the outmost AST nodes are built first, while the node that
+/// immediately contains the constructor would be built last and capture the
+/// previous layers as its parents. Construction context captures the last layer
+/// (which has links to the previous layers) and classifies the seemingly
+/// arbitrary chain of layers into one of the possible ways of constructing
+/// an object in C++ for user-friendly experience.
+class ConstructionContextLayer {
const ConstructionContextLayer *Parent = nullptr;
+ ConstructionContextItem Item;
- ConstructionContextLayer(TriggerTy Trigger,
- const ConstructionContextLayer *Parent)
- : Trigger(Trigger), Parent(Parent) {}
+ ConstructionContextLayer(ConstructionContextItem Item,
+ const ConstructionContextLayer *Parent)
+ : Parent(Parent), Item(Item) {}
public:
static const ConstructionContextLayer *
- create(BumpVectorContext &C, TriggerTy Trigger,
+ create(BumpVectorContext &C, const ConstructionContextItem &Item,
const ConstructionContextLayer *Parent = nullptr);
+ const ConstructionContextItem &getItem() const { return Item; }
const ConstructionContextLayer *getParent() const { return Parent; }
bool isLast() const { return !Parent; }
- const Stmt *getTriggerStmt() const {
- return Trigger.dyn_cast<Stmt *>();
- }
-
- const CXXCtorInitializer *getTriggerInit() const {
- return Trigger.dyn_cast<CXXCtorInitializer *>();
- }
-
- /// Returns true if these layers are equal as individual layers, even if
- /// their parents are different.
- bool isSameLayer(const ConstructionContextLayer *Other) const {
- assert(Other);
- return (Trigger == Other->Trigger);
- }
-
/// See if Other is a proper initial segment of this construction context
/// in terms of the parent chain - i.e. a few first parents coincide and
/// then the other context terminates but our context goes further - i.e.,
@@ -114,7 +249,8 @@ public:
SimpleReturnedValueKind,
CXX17ElidedCopyReturnedValueKind,
RETURNED_VALUE_BEGIN = SimpleReturnedValueKind,
- RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind
+ RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind,
+ ArgumentKind
};
protected:
@@ -132,6 +268,23 @@ private:
return new (CC) T(Args...);
}
+ // A sub-routine of createFromLayers() that deals with temporary objects
+ // that need to be materialized. The BTE argument is for the situation when
+ // the object also needs to be bound for destruction.
+ static const ConstructionContext *createMaterializedTemporaryFromLayers(
+ BumpVectorContext &C, const MaterializeTemporaryExpr *MTE,
+ const CXXBindTemporaryExpr *BTE,
+ const ConstructionContextLayer *ParentLayer);
+
+ // A sub-routine of createFromLayers() that deals with temporary objects
+ // that need to be bound for destruction. Automatically finds out if the
+ // object also needs to be materialized and delegates to
+ // createMaterializedTemporaryFromLayers() if necessary.
+ static const ConstructionContext *
+ createBoundTemporaryFromLayers(
+ BumpVectorContext &C, const CXXBindTemporaryExpr *BTE,
+ const ConstructionContextLayer *ParentLayer);
+
public:
/// Consume the construction context layer, together with its parent layers,
/// and wrap it up into a complete construction context. May return null
@@ -469,6 +622,32 @@ public:
}
};
+class ArgumentConstructionContext : public ConstructionContext {
+ const Expr *CE; // The call of which the context is an argument.
+ unsigned Index; // Which argument we're constructing.
+ const CXXBindTemporaryExpr *BTE; // Whether the object needs to be destroyed.
+
+ friend class ConstructionContext; // Allows to create<>() itself.
+
+ explicit ArgumentConstructionContext(const Expr *CE, unsigned Index,
+ const CXXBindTemporaryExpr *BTE)
+ : ConstructionContext(ArgumentKind), CE(CE),
+ Index(Index), BTE(BTE) {
+ assert(isa<CallExpr>(CE) || isa<CXXConstructExpr>(CE) ||
+ isa<ObjCMessageExpr>(CE));
+ // BTE is optional.
+ }
+
+public:
+ const Expr *getCallLikeExpr() const { return CE; }
+ unsigned getIndex() const { return Index; }
+ const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
+
+ static bool classof(const ConstructionContext *CC) {
+ return CC->getKind() == ArgumentKind;
+ }
+};
+
} // end namespace clang
#endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
diff --git a/include/clang/Analysis/DomainSpecific/CocoaConventions.h b/include/clang/Analysis/DomainSpecific/CocoaConventions.h
index 8b3fcff52d08..9326d1abbac1 100644
--- a/include/clang/Analysis/DomainSpecific/CocoaConventions.h
+++ b/include/clang/Analysis/DomainSpecific/CocoaConventions.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements cocoa naming convention analysis.
+// This file implements cocoa naming convention analysis.
//
//===----------------------------------------------------------------------===//
@@ -20,20 +20,20 @@
namespace clang {
class FunctionDecl;
class QualType;
-
+
namespace ento {
namespace cocoa {
-
+
bool isRefType(QualType RetTy, StringRef Prefix,
StringRef Name = StringRef());
-
+
bool isCocoaObjectRef(QualType T);
}
namespace coreFoundation {
bool isCFObjectRef(QualType T);
-
+
bool followsCreateRule(const FunctionDecl *FD);
}
diff --git a/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h b/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
index f9e800a4a412..e304d83615d4 100644
--- a/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
+++ b/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
@@ -21,7 +21,7 @@ namespace clang {
class ASTContext;
class ObjCMessageExpr;
-
+
class ObjCNoReturn {
/// Cached "raise" selector.
Selector RaiseSel;
@@ -36,7 +36,7 @@ class ObjCNoReturn {
public:
ObjCNoReturn(ASTContext &C);
-
+
/// Return true if the given message expression is known to never
/// return.
bool isImplicitNoReturn(const ObjCMessageExpr *ME);
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index e8f0d61617eb..25ae93fae6b8 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -33,7 +33,7 @@ namespace clang {
class AnalysisDeclContext;
class FunctionDecl;
class LocationContext;
-
+
/// ProgramPoints can be "tagged" as representing points specific to a given
/// analysis entity. Tags are abstract annotations, with an associated
/// description and potentially other information.
@@ -41,12 +41,12 @@ class ProgramPointTag {
public:
ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
virtual ~ProgramPointTag();
- virtual StringRef getTagDescription() const = 0;
+ virtual StringRef getTagDescription() const = 0;
protected:
/// Used to implement 'isKind' in subclasses.
const void *getTagKind() { return TagKind; }
-
+
private:
const void *TagKind;
};
@@ -111,7 +111,7 @@ protected:
assert(getLocationContext() == l);
assert(getData1() == P);
}
-
+
ProgramPoint(const void *P1,
const void *P2,
Kind k,
@@ -223,7 +223,7 @@ class BlockEntrance : public ProgramPoint {
public:
BlockEntrance(const CFGBlock *B, const LocationContext *L,
const ProgramPointTag *tag = nullptr)
- : ProgramPoint(B, BlockEntranceKind, L, tag) {
+ : ProgramPoint(B, BlockEntranceKind, L, tag) {
assert(B && "BlockEntrance requires non-null block");
}
@@ -235,7 +235,7 @@ public:
const CFGBlock *B = getBlock();
return B->empty() ? Optional<CFGElement>() : B->front();
}
-
+
private:
friend class ProgramPoint;
BlockEntrance() = default;
@@ -350,7 +350,7 @@ protected:
LocationCheck(const Stmt *S, const LocationContext *L,
ProgramPoint::Kind K, const ProgramPointTag *tag)
: StmtPoint(S, nullptr, K, L, tag) {}
-
+
private:
friend class ProgramPoint;
static bool isKind(const ProgramPoint &location) {
@@ -358,13 +358,13 @@ private:
return k == PreLoadKind || k == PreStoreKind;
}
};
-
+
class PreLoad : public LocationCheck {
public:
PreLoad(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = nullptr)
: LocationCheck(S, L, PreLoadKind, tag) {}
-
+
private:
friend class ProgramPoint;
PreLoad() = default;
@@ -378,7 +378,7 @@ public:
PreStore(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = nullptr)
: LocationCheck(S, L, PreStoreKind, tag) {}
-
+
private:
friend class ProgramPoint;
PreStore() = default;
@@ -405,7 +405,7 @@ private:
class PostStore : public PostStmt {
public:
/// Construct the post store point.
- /// \param Loc can be used to store the information about the location
+ /// \param Loc can be used to store the information about the location
/// used in the form it was uttered in the code.
PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
const ProgramPointTag *tag = nullptr)
@@ -479,7 +479,7 @@ public:
BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
: ProgramPoint(B1, B2, BlockEdgeKind, L) {
assert(B1 && "BlockEdge: source block must be non-null");
- assert(B2 && "BlockEdge: destination block must be non-null");
+ assert(B2 && "BlockEdge: destination block must be non-null");
}
const CFGBlock *getSrc() const {
@@ -603,7 +603,7 @@ private:
/// CallEnter uses the caller's location context.
class CallEnter : public ProgramPoint {
public:
- CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
+ CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
const LocationContext *callerCtx)
: ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {}
@@ -749,7 +749,7 @@ static bool isEqual(const clang::ProgramPoint &L,
}
};
-
+
template <>
struct isPodLike<clang::ProgramPoint> { static const bool value = true; };
diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h
index 5940520855ef..00a7417e20f9 100644
--- a/include/clang/Analysis/Support/BumpVector.h
+++ b/include/clang/Analysis/Support/BumpVector.h
@@ -29,7 +29,7 @@
#include <type_traits>
namespace clang {
-
+
class BumpVectorContext {
llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1> Alloc;
@@ -47,15 +47,15 @@ public:
/// BumpPtrAllocator. This BumpPtrAllocator is not destroyed when the
/// BumpVectorContext object is destroyed.
BumpVectorContext(llvm::BumpPtrAllocator &A) : Alloc(&A, 0) {}
-
+
~BumpVectorContext() {
if (Alloc.getInt())
delete Alloc.getPointer();
}
-
+
llvm::BumpPtrAllocator &getAllocator() { return *Alloc.getPointer(); }
};
-
+
template<typename T>
class BumpVector {
T *Begin = nullptr;
@@ -67,34 +67,34 @@ public:
explicit BumpVector(BumpVectorContext &C, unsigned N) {
reserve(C, N);
}
-
+
~BumpVector() {
if (std::is_class<T>::value) {
// Destroy the constructed elements in the vector.
destroy_range(Begin, End);
}
}
-
+
using size_type = size_t;
using difference_type = ptrdiff_t;
using value_type = T;
using iterator = T *;
using const_iterator = const T *;
-
+
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using reverse_iterator = std::reverse_iterator<iterator>;
-
+
using reference = T &;
using const_reference = const T &;
using pointer = T *;
using const_pointer = const T *;
-
+
// forward iterator creation methods.
iterator begin() { return Begin; }
const_iterator begin() const { return Begin; }
iterator end() { return End; }
const_iterator end() const { return End; }
-
+
// reverse iterator creation methods.
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
@@ -102,7 +102,7 @@ public:
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
-
+
bool empty() const { return Begin == End; }
size_type size() const { return End-Begin; }
@@ -114,49 +114,49 @@ public:
assert(Begin + idx < End);
return Begin[idx];
}
-
+
reference front() {
return begin()[0];
}
const_reference front() const {
return begin()[0];
}
-
+
reference back() {
return end()[-1];
}
const_reference back() const {
return end()[-1];
}
-
+
void pop_back() {
--End;
End->~T();
}
-
+
T pop_back_val() {
T Result = back();
pop_back();
return Result;
}
-
+
void clear() {
if (std::is_class<T>::value) {
destroy_range(Begin, End);
}
End = Begin;
}
-
+
/// data - Return a pointer to the vector's buffer, even if empty().
pointer data() {
return pointer(Begin);
}
-
+
/// data - Return a pointer to the vector's buffer, even if empty().
const_pointer data() const {
return const_pointer(Begin);
}
-
+
void push_back(const_reference Elt, BumpVectorContext &C) {
if (End < Capacity) {
Retry:
@@ -165,7 +165,7 @@ public:
return;
}
grow(C);
- goto Retry;
+ goto Retry;
}
/// insert - Insert some number of copies of element into a position. Return
@@ -193,18 +193,18 @@ public:
/// capacity - Return the total number of elements in the currently allocated
/// buffer.
- size_t capacity() const { return Capacity - Begin; }
-
+ size_t capacity() const { return Capacity - Begin; }
+
private:
/// grow - double the size of the allocated memory, guaranteeing space for at
/// least one more element or MinSize if specified.
void grow(BumpVectorContext &C, size_type MinSize = 1);
-
+
void construct_range(T *S, T *E, const T &Elt) {
for (; S != E; ++S)
new (S) T(Elt);
}
-
+
void destroy_range(T *S, T *E) {
while (S != E) {
--E;
@@ -220,7 +220,7 @@ private:
}
}
};
-
+
// Define this out-of-line to dissuade the C++ compiler from inlining it.
template <typename T>
void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) {
@@ -232,7 +232,7 @@ void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) {
// Allocate the memory from the BumpPtrAllocator.
T *NewElts = C.getAllocator().template Allocate<T>(NewCapacity);
-
+
// Copy the elements over.
if (Begin != End) {
if (std::is_class<T>::value) {