Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/amd-common' into HEAD
Browse files Browse the repository at this point in the history
  • Loading branch information
rocm-hcc committed Aug 21, 2019
2 parents 3082659 + e6a3c23 commit 61f97b4
Show file tree
Hide file tree
Showing 35 changed files with 1,255 additions and 274 deletions.
29 changes: 27 additions & 2 deletions docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,35 @@ C++ Checkers.
.. _cplusplus-InnerPointer:
cplusplus.InnerPointer
""""""""""""""""""""""
cplusplus.InnerPointer (C++)
""""""""""""""""""""""""""""
Check for inner pointers of C++ containers used after re/deallocation.
Many container methods in the C++ standard library are known to invalidate
"references" (including actual references, iterators and raw pointers) to
elements of the container. Using such references after they are invalidated
causes undefined behavior, which is a common source of memory errors in C++ that
this checker is capable of finding.
The checker is currently limited to ``std::string`` objects and doesn't
recognize some of the more sophisticated approaches to passing unowned pointers
around, such as ``std::string_view``.
.. code-block:: cpp
void deref_after_assignment() {
std::string s = "llvm";
const char *c = s.data(); // note: pointer to inner buffer of 'std::string' obtained here
s = "clang"; // note: inner buffer of 'std::string' reallocated by call to 'operator='
consume(c); // warn: inner pointer of container used after re/deallocation
}
const char *return_temp(int x) {
return std::to_string(x).c_str(); // warn: inner pointer of container used after re/deallocation
// note: pointer to inner buffer of 'std::string' obtained here
// note: inner buffer of 'std::string' deallocated by call to destructor
}
.. _cplusplus-NewDelete:
cplusplus.NewDelete (C++)
Expand Down
77 changes: 71 additions & 6 deletions include/clang/AST/StmtOpenMP.h
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,8 @@ class OMPLoopDirective : public OMPExecutableDirective {
PreInitsOffset = 8,
// The '...End' enumerators do not correspond to child expressions - they
// specify the offset to the end (and start of the following counters/
// updates/finals arrays).
// updates/finals/dependent_counters/dependent_inits/finals_conditions
// arrays).
DefaultEnd = 9,
// The following 8 exprs are used by worksharing and distribute loops only.
IsLastIterVariableOffset = 9,
Expand All @@ -474,7 +475,8 @@ class OMPLoopDirective : public OMPExecutableDirective {
CombinedNextUpperBoundOffset = 27,
CombinedDistConditionOffset = 28,
CombinedParForInDistConditionOffset = 29,
// Offset to the end (and start of the following counters/updates/finals
// Offset to the end (and start of the following
// counters/updates/finals/dependent_counters/dependent_inits/finals_conditions
// arrays) for combined distribute loop directives.
CombinedDistributeEnd = 30,
};
Expand Down Expand Up @@ -517,6 +519,30 @@ class OMPLoopDirective : public OMPExecutableDirective {
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}

/// Get the dependent counters storage.
MutableArrayRef<Expr *> getDependentCounters() {
Expr **Storage = reinterpret_cast<Expr **>(
&*std::next(child_begin(),
getArraysOffset(getDirectiveKind()) + 5 * CollapsedNum));
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}

/// Get the dependent inits storage.
MutableArrayRef<Expr *> getDependentInits() {
Expr **Storage = reinterpret_cast<Expr **>(
&*std::next(child_begin(),
getArraysOffset(getDirectiveKind()) + 6 * CollapsedNum));
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}

/// Get the finals conditions storage.
MutableArrayRef<Expr *> getFinalsConditions() {
Expr **Storage = reinterpret_cast<Expr **>(
&*std::next(child_begin(),
getArraysOffset(getDirectiveKind()) + 7 * CollapsedNum));
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}

protected:
/// Build instance of loop directive of class \a Kind.
///
Expand Down Expand Up @@ -551,9 +577,10 @@ class OMPLoopDirective : public OMPExecutableDirective {
/// Children number.
static unsigned numLoopChildren(unsigned CollapsedNum,
OpenMPDirectiveKind Kind) {
return getArraysOffset(Kind) + 5 * CollapsedNum; // Counters,
// PrivateCounters, Inits,
// Updates and Finals
return getArraysOffset(Kind) +
8 * CollapsedNum; // Counters, PrivateCounters, Inits,
// Updates, Finals, DependentCounters,
// DependentInits, FinalsConditions.
}

void setIterationVariable(Expr *IV) {
Expand Down Expand Up @@ -703,6 +730,9 @@ class OMPLoopDirective : public OMPExecutableDirective {
void setInits(ArrayRef<Expr *> A);
void setUpdates(ArrayRef<Expr *> A);
void setFinals(ArrayRef<Expr *> A);
void setDependentCounters(ArrayRef<Expr *> A);
void setDependentInits(ArrayRef<Expr *> A);
void setFinalsConditions(ArrayRef<Expr *> A);

public:
/// The expressions built to support OpenMP loops in combined/composite
Expand Down Expand Up @@ -798,6 +828,15 @@ class OMPLoopDirective : public OMPExecutableDirective {
SmallVector<Expr *, 4> Updates;
/// Final loop counter values for GodeGen.
SmallVector<Expr *, 4> Finals;
/// List of counters required for the generation of the non-rectangular
/// loops.
SmallVector<Expr *, 4> DependentCounters;
/// List of initializers required for the generation of the non-rectangular
/// loops.
SmallVector<Expr *, 4> DependentInits;
/// List of final conditions required for the generation of the
/// non-rectangular loops.
SmallVector<Expr *, 4> FinalsConditions;
/// Init statement for all captured expressions.
Stmt *PreInits;

Expand All @@ -813,7 +852,9 @@ class OMPLoopDirective : public OMPExecutableDirective {
}

/// Initialize all the fields to null.
/// \param Size Number of elements in the counters/finals/updates arrays.
/// \param Size Number of elements in the
/// counters/finals/updates/dependent_counters/dependent_inits/finals_conditions
/// arrays.
void clear(unsigned Size) {
IterationVarRef = nullptr;
LastIteration = nullptr;
Expand All @@ -839,12 +880,18 @@ class OMPLoopDirective : public OMPExecutableDirective {
Inits.resize(Size);
Updates.resize(Size);
Finals.resize(Size);
DependentCounters.resize(Size);
DependentInits.resize(Size);
FinalsConditions.resize(Size);
for (unsigned i = 0; i < Size; ++i) {
Counters[i] = nullptr;
PrivateCounters[i] = nullptr;
Inits[i] = nullptr;
Updates[i] = nullptr;
Finals[i] = nullptr;
DependentCounters[i] = nullptr;
DependentInits[i] = nullptr;
FinalsConditions[i] = nullptr;
}
PreInits = nullptr;
DistCombinedFields.LB = nullptr;
Expand Down Expand Up @@ -1078,6 +1125,24 @@ class OMPLoopDirective : public OMPExecutableDirective {
return const_cast<OMPLoopDirective *>(this)->getFinals();
}

ArrayRef<Expr *> dependent_counters() { return getDependentCounters(); }

ArrayRef<Expr *> dependent_counters() const {
return const_cast<OMPLoopDirective *>(this)->getDependentCounters();
}

ArrayRef<Expr *> dependent_inits() { return getDependentInits(); }

ArrayRef<Expr *> dependent_inits() const {
return const_cast<OMPLoopDirective *>(this)->getDependentInits();
}

ArrayRef<Expr *> finals_conditions() { return getFinalsConditions(); }

ArrayRef<Expr *> finals_conditions() const {
return const_cast<OMPLoopDirective *>(this)->getFinalsConditions();
}

static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPSimdDirectiveClass ||
T->getStmtClass() == OMPForDirectiveClass ||
Expand Down
3 changes: 2 additions & 1 deletion include/clang/Driver/CC1Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ def analyzer_checker_help_developer : Flag<["-"], "analyzer-checker-help-develop
"and debug checkers">;

def analyzer_config_help : Flag<["-"], "analyzer-config-help">,
HelpText<"Display the list of -analyzer-config options">;
HelpText<"Display the list of -analyzer-config options. These are meant for "
"development purposes only!">;

def analyzer_list_enabled_checkers : Flag<["-"], "analyzer-list-enabled-checkers">,
HelpText<"Display the list of enabled analyzer checkers">;
Expand Down
6 changes: 4 additions & 2 deletions include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,12 @@ class BugReport : public llvm::ilist_node<BugReport> {
/// to the user. This method allows to rest the location which should be used
/// for uniquing reports. For example, memory leaks checker, could set this to
/// the allocation site, rather then the location where the bug is reported.
BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode,
BugReport(BugType &bt, StringRef desc, const ExplodedNode *errornode,
PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique)
: BT(bt), Description(desc), UniqueingLocation(LocationToUnique),
UniqueingDecl(DeclToUnique), ErrorNode(errornode) {}
UniqueingDecl(DeclToUnique), ErrorNode(errornode),
ErrorNodeRange(getStmt() ? getStmt()->getSourceRange()
: SourceRange()) {}

virtual ~BugReport() = default;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,6 @@ class FindLastStoreBRVisitor final : public BugReporterVisitor {

/// \param V We're searching for the store where \c R received this value.
/// \param R The region we're tracking.
/// \param EnableNullFPSuppression Whether we should employ false positive
/// suppression (inlined defensive checks, returned null).
/// \param TKind May limit the amount of notes added to the bug report.
/// \param OriginSFC Only adds notes when the last store happened in a
/// different stackframe to this one. Disregarded if the tracking kind
Expand Down
Loading

0 comments on commit 61f97b4

Please sign in to comment.