Skip to content

Commit

Permalink
Merge from 'master' to 'sycl-web' (intel#9)
Browse files Browse the repository at this point in the history
  CONFLICT (content): Merge conflict in clang/lib/CodeGen/CGExpr.cpp
  • Loading branch information
bader committed Dec 4, 2019
2 parents 1d69c83 + 9f37c0e commit 407bb95
Show file tree
Hide file tree
Showing 43 changed files with 782 additions and 614 deletions.
133 changes: 13 additions & 120 deletions clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,44 +19,6 @@ namespace clang {
namespace tidy {
namespace readability {

namespace {
class NamespaceCommentPPCallbacks : public PPCallbacks {
public:
NamespaceCommentPPCallbacks(Preprocessor *PP, NamespaceCommentCheck *Check)
: PP(PP), Check(Check) {}

void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) {
// Record all defined macros. We store the whole token to compare names
// later.

const MacroInfo * MI = MD->getMacroInfo();

if (MI->isFunctionLike())
return;

std::string ValueBuffer;
llvm::raw_string_ostream Value(ValueBuffer);

SmallString<128> SpellingBuffer;
bool First = true;
for (const auto &T : MI->tokens()) {
if (!First && T.hasLeadingSpace())
Value << ' ';

Value << PP->getSpelling(T, SpellingBuffer);
First = false;
}

Check->addMacro(MacroNameTok.getIdentifierInfo()->getName().str(),
Value.str());
}

private:
Preprocessor *PP;
NamespaceCommentCheck *Check;
};
} // namespace

NamespaceCommentCheck::NamespaceCommentCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
Expand All @@ -78,70 +40,31 @@ void NamespaceCommentCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(namespaceDecl().bind("namespace"), this);
}

void NamespaceCommentCheck::registerPPCallbacks(
const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
PP->addPPCallbacks(std::make_unique<NamespaceCommentPPCallbacks>(PP, this));
}

static bool locationsInSameFile(const SourceManager &Sources,
SourceLocation Loc1, SourceLocation Loc2) {
return Loc1.isFileID() && Loc2.isFileID() &&
Sources.getFileID(Loc1) == Sources.getFileID(Loc2);
}

std::string NamespaceCommentCheck::getNamespaceComment(const NamespaceDecl *ND,
bool InsertLineBreak) {
static std::string getNamespaceComment(const NamespaceDecl *ND,
bool InsertLineBreak) {
std::string Fix = "// namespace";
if (!ND->isAnonymousNamespace()) {
bool IsNamespaceMacroExpansion;
StringRef MacroDefinition;
std::tie(IsNamespaceMacroExpansion, MacroDefinition) =
isNamespaceMacroExpansion(ND->getName());

Fix.append(" ").append(IsNamespaceMacroExpansion ? MacroDefinition
: ND->getName());
}
if (!ND->isAnonymousNamespace())
Fix.append(" ").append(ND->getNameAsString());
if (InsertLineBreak)
Fix.append("\n");
return Fix;
}

std::string
NamespaceCommentCheck::getNamespaceComment(const std::string &NameSpaceName,
bool InsertLineBreak) {
static std::string getNamespaceComment(const std::string &NameSpaceName,
bool InsertLineBreak) {
std::string Fix = "// namespace ";
Fix.append(NameSpaceName);
if (InsertLineBreak)
Fix.append("\n");
return Fix;
}

void NamespaceCommentCheck::addMacro(const std::string &Name,
const std::string &Value) noexcept {
Macros.emplace_back(Name, Value);
}

bool NamespaceCommentCheck::isNamespaceMacroDefinition(
const StringRef NameSpaceName) {
return llvm::any_of(Macros, [&NameSpaceName](const auto &Macro) {
return NameSpaceName == Macro.first;
});
}

std::tuple<bool, StringRef> NamespaceCommentCheck::isNamespaceMacroExpansion(
const StringRef NameSpaceName) {
const auto &MacroIt =
llvm::find_if(Macros, [&NameSpaceName](const auto &Macro) {
return NameSpaceName == Macro.second;
});

const bool IsNamespaceMacroExpansion = Macros.end() != MacroIt;

return std::make_tuple(IsNamespaceMacroExpansion,
IsNamespaceMacroExpansion ? StringRef(MacroIt->first)
: NameSpaceName);
}

void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
const auto *ND = Result.Nodes.getNodeAs<NamespaceDecl>("namespace");
const SourceManager &Sources = *Result.SourceManager;
Expand Down Expand Up @@ -220,48 +143,28 @@ void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
StringRef NamespaceNameInComment = Groups.size() > 5 ? Groups[5] : "";
StringRef Anonymous = Groups.size() > 3 ? Groups[3] : "";

// Don't allow to use macro expansion in closing comment.
// FIXME: Use Structured Bindings once C++17 features will be enabled.
bool IsNamespaceMacroExpansion;
StringRef MacroDefinition;
std::tie(IsNamespaceMacroExpansion, MacroDefinition) =
isNamespaceMacroExpansion(NamespaceNameInComment);

if (IsNested && NestedNamespaceName == NamespaceNameInComment) {
// C++17 nested namespace.
return;
} else if ((ND->isAnonymousNamespace() &&
NamespaceNameInComment.empty()) ||
(((ND->getNameAsString() == NamespaceNameInComment) &&
Anonymous.empty()) &&
!IsNamespaceMacroExpansion)) {
(ND->getNameAsString() == NamespaceNameInComment &&
Anonymous.empty())) {
// Check if the namespace in the comment is the same.
// FIXME: Maybe we need a strict mode, where we always fix namespace
// comments with different format.
return;
}

// Allow using macro definitions in closing comment.
if (isNamespaceMacroDefinition(NamespaceNameInComment))
return;

// Otherwise we need to fix the comment.
NeedLineBreak = Comment.startswith("/*");
OldCommentRange =
SourceRange(AfterRBrace, Loc.getLocWithOffset(Tok.getLength()));

if (IsNamespaceMacroExpansion) {
Message = (llvm::Twine("%0 ends with a comment that refers to an "
"expansion of macro"))
.str();
NestedNamespaceName = MacroDefinition;
} else {
Message = (llvm::Twine("%0 ends with a comment that refers to a "
"wrong namespace '") +
NamespaceNameInComment + "'")
.str();
}

Message =
(llvm::Twine(
"%0 ends with a comment that refers to a wrong namespace '") +
NamespaceNameInComment + "'")
.str();
} else if (Comment.startswith("//")) {
// Assume that this is an unrecognized form of a namespace closing line
// comment. Replace it.
Expand All @@ -274,16 +177,6 @@ void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) {
// multi-line or there may be other tokens behind it.
}

// Print Macro definition instead of expansion.
// FIXME: Use Structured Bindings once C++17 features will be enabled.
bool IsNamespaceMacroExpansion;
StringRef MacroDefinition;
std::tie(IsNamespaceMacroExpansion, MacroDefinition) =
isNamespaceMacroExpansion(NestedNamespaceName);

if (IsNamespaceMacroExpansion)
NestedNamespaceName = MacroDefinition;

std::string NamespaceName =
ND->isAnonymousNamespace()
? "anonymous namespace"
Expand Down
15 changes: 0 additions & 15 deletions clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,14 @@ class NamespaceCommentCheck : public ClangTidyCheck {
NamespaceCommentCheck(StringRef Name, ClangTidyContext *Context);
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
Preprocessor *ModuleExpanderPP) override;

void addMacro(const std::string &Name, const std::string &Value) noexcept;

private:
void storeOptions(ClangTidyOptions::OptionMap &Options) override;
std::string getNamespaceComment(const NamespaceDecl *ND,
bool InsertLineBreak);
std::string getNamespaceComment(const std::string &NameSpaceName,
bool InsertLineBreak);
bool isNamespaceMacroDefinition(const StringRef NameSpaceName);
std::tuple<bool, StringRef>
isNamespaceMacroExpansion(const StringRef NameSpaceName);

llvm::Regex NamespaceCommentPattern;
const unsigned ShortNamespaceLines;
const unsigned SpacesBeforeComments;
llvm::SmallVector<SourceLocation, 4> Ends;

// Store macros to verify that warning is not thrown when namespace name is a
// preprocessed define.
std::vector<std::pair<std::string, std::string>> Macros;
};

} // namespace readability
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ void f(); // So that the namespace isn't empty.
// 5
// 6
// 7
// CHECK-MESSAGES: :[[@LINE+2]]:1: warning: namespace 'MACRO' not terminated with
// CHECK-MESSAGES: :[[@LINE-10]]:11: note: namespace 'MACRO' starts here
// CHECK-MESSAGES: :[[@LINE+2]]:1: warning: namespace 'macro_expansion' not terminated with
// CHECK-MESSAGES: :[[@LINE-10]]:11: note: namespace 'macro_expansion' starts here
}
// CHECK-FIXES: } // namespace MACRO
// CHECK-FIXES: } // namespace macro_expansion

namespace short1 {
namespace short2 {
Expand Down

This file was deleted.

34 changes: 34 additions & 0 deletions clang/docs/SourceBasedCodeCoverage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,37 @@ Drawbacks and limitations
If the call to ``may_throw()`` propagates an exception into ``f``, the code
coverage tool may mark the ``return`` statement as executed even though it is
not. A call to ``longjmp()`` can have similar effects.

Clang implementation details
============================

This section may be of interest to those wishing to understand or improve
the clang code coverage implementation.

Gap regions
-----------

Gap regions are source regions with counts. A reporting tool cannot set a line
execution count to the count from a gap region unless that region is the only
one on a line.

Gap regions are used to eliminate unnatural artifacts in coverage reports, such
as red "unexecuted" highlights present at the end of an otherwise covered line,
or blue "executed" highlights present at the start of a line that is otherwise
not executed.

Switch statements
-----------------

The region mapping for a switch body consists of a gap region that covers the
entire body (starting from the '{' in 'switch (...) {', and terminating where the
last case ends). This gap region has a zero count: this causes "gap" areas in
between case statements, which contain no executable code, to appear uncovered.

When a switch case is visited, the parent region is extended: if the parent
region has no start location, its start location becomes the start of the case.
This is used to support switch statements without a ``CompoundStmt`` body, in
which the switch body and the single case share a count.

For switches with ``CompoundStmt`` bodies, a new region is created at the start
of each switch case.
3 changes: 2 additions & 1 deletion clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,7 @@ def ZeroLengthArray : DiagGroup<"zero-length-array">;
def GNUZeroLineDirective : DiagGroup<"gnu-zero-line-directive">;
def GNUZeroVariadicMacroArguments : DiagGroup<"gnu-zero-variadic-macro-arguments">;
def Fallback : DiagGroup<"fallback">;
def MisleadingIndentation : DiagGroup<"misleading-indentation">;

// This covers both the deprecated case (in C++98)
// and the extension case (in C++11 onwards).
Expand Down Expand Up @@ -884,7 +885,7 @@ def Consumed : DiagGroup<"consumed">;
// Note that putting warnings in -Wall will not disable them by default. If a
// warning should be active _only_ when -Wall is passed in, mark it as
// DefaultIgnore in addition to putting it here.
def All : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool]>;
def All : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool, MisleadingIndentation]>;

// Warnings that should be in clang-cl /w4.
def : DiagGroup<"CL4", [All, Extra]>;
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ def warn_null_statement : Warning<
"remove unnecessary ';' to silence this warning">,
InGroup<ExtraSemiStmt>, DefaultIgnore;

def warn_misleading_indentation : Warning<
"misleading indentation; statement is not part of "
"the previous '%select{if|else|for|while|else if}0'">,
InGroup<MisleadingIndentation>, DefaultIgnore;
def note_previous_statement : Note<
"previous statement is here">;

def ext_thread_before : Extension<"'__thread' before '%0'">;
def ext_keyword_as_ident : ExtWarn<
"keyword '%0' will be made available as an identifier "
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Lex/Preprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,12 @@ class Preprocessor {
return TheModuleLoader.HadFatalFailure;
}

/// Retrieve the number of Directives that have been processed by the
/// Preprocessor.
unsigned getNumDirectives() const {
return NumDirectives;
}

/// True if we are currently preprocessing a #if or #elif directive
bool isParsingIfOrElifDirective() const {
return ParsingIfOrElifDirective;
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,11 @@ class Parser : public CodeCompletionHandler {
/// point for skipping past a simple-declaration.
void SkipMalformedDecl();

/// The location of the first statement inside an else that might
/// have a missleading indentation. If there is no
/// MisleadingIndentationChecker on an else active, this location is invalid.
SourceLocation MisleadingIndentationElseLoc;

private:
//===--------------------------------------------------------------------===//
// Lexing and parsing of C++ inline methods.
Expand Down
Loading

0 comments on commit 407bb95

Please sign in to comment.