Skip to content

Commit

Permalink
[analyzer][PlistMacroExpansion] Part 1.: New expand-macros flag
Browse files Browse the repository at this point in the history
This is the first part of the implementation of the inclusion of macro
expansions into the plist output. It adds a new flag that adds a new
"macro_expansions" entry to each report that has PathDiagnosticPieces that were
expanded from a macro. While there's an entry for each macro expansion, both
the name of the macro and what it expands to is missing, and will be implemented
in followup patches.

Differential Revision: https://reviews.llvm.org/D52742

llvm-svn: 345724
  • Loading branch information
Szelethus committed Oct 31, 2018
1 parent 412ed34 commit 7d6d9eb
Show file tree
Hide file tree
Showing 6 changed files with 506 additions and 15 deletions.
10 changes: 10 additions & 0 deletions clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
Expand Up @@ -307,6 +307,9 @@ class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
/// \sa shouldDisplayNotesAsEvents
Optional<bool> DisplayNotesAsEvents;

/// \sa shouldDisplayMacroExpansions
Optional<bool> DisplayMacroExpansions;

/// \sa shouldAggressivelySimplifyBinaryOperation
Optional<bool> AggressiveBinaryOperationSimplification;

Expand Down Expand Up @@ -693,6 +696,13 @@ class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
/// to false when unset.
bool shouldDisplayNotesAsEvents();

/// Returns true if macros related to the bugpath should be expanded and
/// included in the plist output.
///
/// This is controlled by the 'expand-macros' option, which defaults to false
/// when unset.
bool shouldDisplayMacroExpansions();

/// Returns true if SValBuilder should rearrange comparisons and additive
/// operations of symbolic expressions which consist of a sum of a symbol and
/// a concrete integer into the format where symbols are on the left-hand
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
Expand Up @@ -464,6 +464,13 @@ bool AnalyzerOptions::shouldDisplayNotesAsEvents() {
return DisplayNotesAsEvents.getValue();
}

bool AnalyzerOptions::shouldDisplayMacroExpansions() {
if (!DisplayMacroExpansions.hasValue())
DisplayMacroExpansions =
getBooleanOption("expand-macros", /*Default=*/false);
return DisplayMacroExpansions.getValue();
}

bool AnalyzerOptions::shouldAggressivelySimplifyBinaryOperation() {
if (!AggressiveBinaryOperationSimplification.hasValue())
AggressiveBinaryOperationSimplification =
Expand Down
18 changes: 11 additions & 7 deletions clang/lib/StaticAnalyzer/Core/BugReporter.cpp
Expand Up @@ -546,7 +546,8 @@ static void updateStackPiecesWithMessage(PathDiagnosticPiece &P,
}
}

static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM);
static void CompactMacroExpandedPieces(PathPieces &path,
const SourceManager& SM);


std::shared_ptr<PathDiagnosticControlFlowPiece> generateDiagForSwitchOP(
Expand Down Expand Up @@ -1972,8 +1973,6 @@ static std::unique_ptr<PathDiagnostic> generatePathDiagnosticForConsumer(
PathDiagnosticLocation::createBegin(D, SM));
}

if (!AddPathEdges && GenerateDiagnostics)
CompactPathDiagnostic(PD->getMutablePieces(), SM);

// Finally, prune the diagnostic path of uninteresting stuff.
if (!PD->path.empty()) {
Expand Down Expand Up @@ -2007,6 +2006,10 @@ static std::unique_ptr<PathDiagnostic> generatePathDiagnosticForConsumer(
removeRedundantMsgs(PD->getMutablePieces());
removeEdgesToDefaultInitializers(PD->getMutablePieces());
}

if (GenerateDiagnostics && Opts.shouldDisplayMacroExpansions())
CompactMacroExpandedPieces(PD->getMutablePieces(), SM);

return PD;
}

Expand Down Expand Up @@ -2436,9 +2439,10 @@ bool TrimmedGraph::popNextReportGraph(ReportGraph &GraphWrapper) {
return true;
}

/// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
/// and collapses PathDiagosticPieces that are expanded by macros.
static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) {
/// CompactMacroExpandedPieces - This function postprocesses a PathDiagnostic
/// object and collapses PathDiagosticPieces that are expanded by macros.
static void CompactMacroExpandedPieces(PathPieces &path,
const SourceManager& SM) {
using MacroStackTy =
std::vector<
std::pair<std::shared_ptr<PathDiagnosticMacroPiece>, SourceLocation>>;
Expand All @@ -2454,7 +2458,7 @@ static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) {

// Recursively compact calls.
if (auto *call = dyn_cast<PathDiagnosticCallPiece>(&*piece)) {
CompactPathDiagnostic(call->path, SM);
CompactMacroExpandedPieces(call->path, SM);
}

// Get the location of the PathDiagnosticPiece.
Expand Down
91 changes: 83 additions & 8 deletions clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
Expand Up @@ -72,6 +72,7 @@ class PlistPrinter {
const FIDMap& FM;
AnalyzerOptions &AnOpts;
const Preprocessor &PP;
llvm::SmallVector<const PathDiagnosticMacroPiece *, 0> MacroPieces;

public:
PlistPrinter(const FIDMap& FM, AnalyzerOptions &AnOpts,
Expand All @@ -86,6 +87,14 @@ class PlistPrinter {
(void)AnOpts;
}

/// Print the expansions of the collected macro pieces.
///
/// Each time ReportDiag is called on a PathDiagnosticMacroPiece (or, if one
/// is found through a call piece, etc), it's subpieces are reported, and the
/// piece itself is collected. Call this function after the entire bugpath
/// was reported.
void ReportMacroExpansions(raw_ostream &o, unsigned indent);

private:
void ReportPiece(raw_ostream &o, const PathDiagnosticPiece &P,
unsigned indent, unsigned depth, bool includeControlFlow,
Expand All @@ -104,7 +113,8 @@ class PlistPrinter {
isKeyEvent);
break;
case PathDiagnosticPiece::Macro:
ReportMacro(o, cast<PathDiagnosticMacroPiece>(P), indent, depth);
ReportMacroSubPieces(o, cast<PathDiagnosticMacroPiece>(P), indent,
depth);
break;
case PathDiagnosticPiece::Note:
ReportNote(o, cast<PathDiagnosticNotePiece>(P), indent);
Expand All @@ -123,14 +133,25 @@ class PlistPrinter {
unsigned indent, unsigned depth, bool isKeyEvent = false);
void ReportCall(raw_ostream &o, const PathDiagnosticCallPiece &P,
unsigned indent, unsigned depth);
void ReportMacro(raw_ostream &o, const PathDiagnosticMacroPiece& P,
unsigned indent, unsigned depth);
void ReportMacroSubPieces(raw_ostream &o, const PathDiagnosticMacroPiece& P,
unsigned indent, unsigned depth);
void ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P,
unsigned indent);
};

} // end of anonymous namespace

namespace {

struct ExpansionInfo {
std::string MacroName;
std::string Expansion;
ExpansionInfo(std::string N, std::string E)
: MacroName(std::move(N)), Expansion(std::move(E)) {}
};

} // end of anonymous namespace

static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
AnalyzerOptions &AnOpts,
const Preprocessor &PP,
Expand All @@ -143,6 +164,10 @@ static void printCoverage(const PathDiagnostic *D,
SmallVectorImpl<FileID> &Fids,
FIDMap &FM,
llvm::raw_fd_ostream &o);

static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc,
const Preprocessor &PP);

//===----------------------------------------------------------------------===//
// Methods of PlistPrinter.
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -299,16 +324,52 @@ void PlistPrinter::ReportCall(raw_ostream &o, const PathDiagnosticCallPiece &P,
ReportPiece(o, *callExit, indent, depth, /*includeControlFlow*/ true);
}

void PlistPrinter::ReportMacro(raw_ostream &o,
const PathDiagnosticMacroPiece& P,
unsigned indent, unsigned depth) {
void PlistPrinter::ReportMacroSubPieces(raw_ostream &o,
const PathDiagnosticMacroPiece& P,
unsigned indent, unsigned depth) {
MacroPieces.push_back(&P);

for (PathPieces::const_iterator I = P.subPieces.begin(), E=P.subPieces.end();
I!=E; ++I) {
for (PathPieces::const_iterator I = P.subPieces.begin(),
E = P.subPieces.end();
I != E; ++I) {
ReportPiece(o, **I, indent, depth, /*includeControlFlow*/ false);
}
}

void PlistPrinter::ReportMacroExpansions(raw_ostream &o, unsigned indent) {

for (const PathDiagnosticMacroPiece *P : MacroPieces) {
const SourceManager &SM = PP.getSourceManager();
ExpansionInfo EI = getExpandedMacro(P->getLocation().asLocation(), PP);

Indent(o, indent) << "<dict>\n";
++indent;

// Output the location.
FullSourceLoc L = P->getLocation().asLocation();

Indent(o, indent) << "<key>location</key>\n";
EmitLocation(o, SM, L, FM, indent);

// Output the ranges (if any).
ArrayRef<SourceRange> Ranges = P->getRanges();
EmitRanges(o, Ranges, indent);

// Output the macro name.
Indent(o, indent) << "<key>name</key>";
EmitString(o, EI.MacroName) << '\n';

// Output what it expands into.
Indent(o, indent) << "<key>expansion</key>";
EmitString(o, EI.Expansion) << '\n';

// Finish up.
--indent;
Indent(o, indent);
o << "</dict>\n";
}
}

void PlistPrinter::ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P,
unsigned indent) {

Expand Down Expand Up @@ -339,6 +400,12 @@ void PlistPrinter::ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P,
// Static function definitions.
//===----------------------------------------------------------------------===//

static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc,
const Preprocessor &PP) {
// TODO: Implement macro expansion.
return { "", "" };
}

/// Print coverage information to output stream {@code o}.
/// May modify the used list of files {@code Fids} by inserting new ones.
static void printCoverage(const PathDiagnostic *D,
Expand Down Expand Up @@ -408,6 +475,14 @@ static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
Printer.ReportDiag(o, **I);

o << " </array>\n";

if (!AnOpts.shouldDisplayMacroExpansions())
return;

o << " <key>macro_expansions</key>\n"
" <array>\n";
Printer.ReportMacroExpansions(o, /* indent */ 4);
o << " </array>\n";
}

//===----------------------------------------------------------------------===//
Expand Down

0 comments on commit 7d6d9eb

Please sign in to comment.