Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@@ -0,0 +1,18 @@
set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyLLVMModule
HeaderGuardCheck.cpp
IncludeOrderCheck.cpp
LLVMTidyModule.cpp
TwineLocalCheck.cpp
LINK_LIBS
clangAST
clangASTMatchers
clangBasic
clangLex
clangTidy
clangTidyReadabilityModule
clangTidyUtils
clangTooling
)

View File

@@ -0,0 +1,55 @@
//===--- HeaderGuardCheck.cpp - clang-tidy --------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "HeaderGuardCheck.h"
namespace clang {
namespace tidy {
namespace llvm {
LLVMHeaderGuardCheck::LLVMHeaderGuardCheck(StringRef Name,
ClangTidyContext *Context)
: HeaderGuardCheck(Name, Context) {}
std::string LLVMHeaderGuardCheck::getHeaderGuard(StringRef Filename,
StringRef OldGuard) {
std::string Guard = tooling::getAbsolutePath(Filename);
// Sanitize the path. There are some rules for compatibility with the historic
// style in include/llvm and include/clang which we want to preserve.
// We don't want _INCLUDE_ in our guards.
size_t PosInclude = Guard.rfind("include/");
if (PosInclude != StringRef::npos)
Guard = Guard.substr(PosInclude + std::strlen("include/"));
// For clang we drop the _TOOLS_.
size_t PosToolsClang = Guard.rfind("tools/clang/");
if (PosToolsClang != StringRef::npos)
Guard = Guard.substr(PosToolsClang + std::strlen("tools/"));
// The remainder is LLVM_FULL_PATH_TO_HEADER_H
size_t PosLLVM = Guard.rfind("llvm/");
if (PosLLVM != StringRef::npos)
Guard = Guard.substr(PosLLVM);
std::replace(Guard.begin(), Guard.end(), '/', '_');
std::replace(Guard.begin(), Guard.end(), '.', '_');
std::replace(Guard.begin(), Guard.end(), '-', '_');
// The prevalent style in clang is LLVM_CLANG_FOO_BAR_H
if (StringRef(Guard).startswith("clang"))
Guard = "LLVM_" + Guard;
return StringRef(Guard).upper();
}
} // namespace llvm
} // namespace tidy
} // namespace clang

View File

@@ -0,0 +1,40 @@
//===--- HeaderGuardCheck.h - clang-tidy ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_HEADER_GUARD_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_HEADER_GUARD_CHECK_H
#include "../utils/HeaderGuard.h"
namespace clang {
namespace tidy {
namespace llvm {
/// Finds and fixes header guards that do not adhere to LLVM style.
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/llvm-header-guard.html
/// The check supports these options:
/// - `HeaderFileExtensions`: a comma-separated list of filename extensions of
/// header files (The filename extension should not contain "." prefix).
/// ",h,hh,hpp,hxx" by default.
/// For extension-less header files, using an empty string or leaving an
/// empty string between "," if there are other filename extensions.
class LLVMHeaderGuardCheck : public utils::HeaderGuardCheck {
public:
LLVMHeaderGuardCheck(StringRef Name, ClangTidyContext *Context);
bool shouldSuggestEndifComment(StringRef Filename) override { return false; }
std::string getHeaderGuard(StringRef Filename, StringRef OldGuard) override;
};
} // namespace llvm
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_HEADER_GUARD_CHECK_H

View File

@@ -0,0 +1,179 @@
//===--- IncludeOrderCheck.cpp - clang-tidy -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "IncludeOrderCheck.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
#include <map>
namespace clang {
namespace tidy {
namespace llvm {
namespace {
class IncludeOrderPPCallbacks : public PPCallbacks {
public:
explicit IncludeOrderPPCallbacks(ClangTidyCheck &Check, SourceManager &SM)
: LookForMainModule(true), Check(Check), SM(SM) {}
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
StringRef FileName, bool IsAngled,
CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath,
const Module *Imported) override;
void EndOfMainFile() override;
private:
struct IncludeDirective {
SourceLocation Loc; ///< '#' location in the include directive
CharSourceRange Range; ///< SourceRange for the file name
std::string Filename; ///< Filename as a string
bool IsAngled; ///< true if this was an include with angle brackets
bool IsMainModule; ///< true if this was the first include in a file
};
typedef std::vector<IncludeDirective> FileIncludes;
std::map<clang::FileID, FileIncludes> IncludeDirectives;
bool LookForMainModule;
ClangTidyCheck &Check;
SourceManager &SM;
};
} // namespace
void IncludeOrderCheck::registerPPCallbacks(CompilerInstance &Compiler) {
Compiler.getPreprocessor().addPPCallbacks(
::llvm::make_unique<IncludeOrderPPCallbacks>(
*this, Compiler.getSourceManager()));
}
static int getPriority(StringRef Filename, bool IsAngled, bool IsMainModule) {
// We leave the main module header at the top.
if (IsMainModule)
return 0;
// LLVM and clang headers are in the penultimate position.
if (Filename.startswith("llvm/") || Filename.startswith("llvm-c/") ||
Filename.startswith("clang/") || Filename.startswith("clang-c/"))
return 2;
// System headers are sorted to the end.
if (IsAngled || Filename.startswith("gtest/"))
return 3;
// Other headers are inserted between the main module header and LLVM headers.
return 1;
}
void IncludeOrderPPCallbacks::InclusionDirective(
SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
StringRef SearchPath, StringRef RelativePath, const Module *Imported) {
// We recognize the first include as a special main module header and want
// to leave it in the top position.
IncludeDirective ID = {HashLoc, FilenameRange, FileName, IsAngled, false};
if (LookForMainModule && !IsAngled) {
ID.IsMainModule = true;
LookForMainModule = false;
}
// Bucket the include directives by the id of the file they were declared in.
IncludeDirectives[SM.getFileID(HashLoc)].push_back(std::move(ID));
}
void IncludeOrderPPCallbacks::EndOfMainFile() {
LookForMainModule = true;
if (IncludeDirectives.empty())
return;
// TODO: find duplicated includes.
// Form blocks of includes. We don't want to sort across blocks. This also
// implicitly makes us never reorder over #defines or #if directives.
// FIXME: We should be more careful about sorting below comments as we don't
// know if the comment refers to the next include or the whole block that
// follows.
for (auto &Bucket : IncludeDirectives) {
auto &FileDirectives = Bucket.second;
std::vector<unsigned> Blocks(1, 0);
for (unsigned I = 1, E = FileDirectives.size(); I != E; ++I)
if (SM.getExpansionLineNumber(FileDirectives[I].Loc) !=
SM.getExpansionLineNumber(FileDirectives[I - 1].Loc) + 1)
Blocks.push_back(I);
Blocks.push_back(FileDirectives.size()); // Sentinel value.
// Get a vector of indices.
std::vector<unsigned> IncludeIndices;
for (unsigned I = 0, E = FileDirectives.size(); I != E; ++I)
IncludeIndices.push_back(I);
// Sort the includes. We first sort by priority, then lexicographically.
for (unsigned BI = 0, BE = Blocks.size() - 1; BI != BE; ++BI)
std::sort(IncludeIndices.begin() + Blocks[BI],
IncludeIndices.begin() + Blocks[BI + 1],
[&FileDirectives](unsigned LHSI, unsigned RHSI) {
IncludeDirective &LHS = FileDirectives[LHSI];
IncludeDirective &RHS = FileDirectives[RHSI];
int PriorityLHS =
getPriority(LHS.Filename, LHS.IsAngled, LHS.IsMainModule);
int PriorityRHS =
getPriority(RHS.Filename, RHS.IsAngled, RHS.IsMainModule);
return std::tie(PriorityLHS, LHS.Filename) <
std::tie(PriorityRHS, RHS.Filename);
});
// Emit a warning for each block and fixits for all changes within that
// block.
for (unsigned BI = 0, BE = Blocks.size() - 1; BI != BE; ++BI) {
// Find the first include that's not in the right position.
unsigned I, E;
for (I = Blocks[BI], E = Blocks[BI + 1]; I != E; ++I)
if (IncludeIndices[I] != I)
break;
if (I == E)
continue;
// Emit a warning.
auto D = Check.diag(FileDirectives[I].Loc,
"#includes are not sorted properly");
// Emit fix-its for all following includes in this block.
for (; I != E; ++I) {
if (IncludeIndices[I] == I)
continue;
const IncludeDirective &CopyFrom = FileDirectives[IncludeIndices[I]];
SourceLocation FromLoc = CopyFrom.Range.getBegin();
const char *FromData = SM.getCharacterData(FromLoc);
unsigned FromLen = std::strcspn(FromData, "\n");
StringRef FixedName(FromData, FromLen);
SourceLocation ToLoc = FileDirectives[I].Range.getBegin();
const char *ToData = SM.getCharacterData(ToLoc);
unsigned ToLen = std::strcspn(ToData, "\n");
auto ToRange =
CharSourceRange::getCharRange(ToLoc, ToLoc.getLocWithOffset(ToLen));
D << FixItHint::CreateReplacement(ToRange, FixedName);
}
}
}
IncludeDirectives.clear();
}
} // namespace llvm
} // namespace tidy
} // namespace clang

View File

@@ -0,0 +1,33 @@
//===--- IncludeOrderCheck.h - clang-tidy -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_INCLUDE_ORDER_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_INCLUDE_ORDER_CHECK_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace llvm {
/// Checks the correct order of `#includes`.
///
/// See http://llvm.org/docs/CodingStandards.html#include-style
class IncludeOrderCheck : public ClangTidyCheck {
public:
IncludeOrderCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerPPCallbacks(CompilerInstance &Compiler) override;
};
} // namespace llvm
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_INCLUDE_ORDER_CHECK_H

View File

@@ -0,0 +1,44 @@
//===--- LLVMTidyModule.cpp - clang-tidy ----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "../readability/NamespaceCommentCheck.h"
#include "HeaderGuardCheck.h"
#include "IncludeOrderCheck.h"
#include "TwineLocalCheck.h"
namespace clang {
namespace tidy {
namespace llvm {
class LLVMModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
CheckFactories.registerCheck<LLVMHeaderGuardCheck>("llvm-header-guard");
CheckFactories.registerCheck<IncludeOrderCheck>("llvm-include-order");
CheckFactories.registerCheck<readability::NamespaceCommentCheck>(
"llvm-namespace-comment");
CheckFactories.registerCheck<TwineLocalCheck>("llvm-twine-local");
}
};
// Register the LLVMTidyModule using this statically initialized variable.
static ClangTidyModuleRegistry::Add<LLVMModule> X("llvm-module",
"Adds LLVM lint checks.");
} // namespace llvm
// This anchor is used to force the linker to link in the generated object file
// and thus register the LLVMModule.
volatile int LLVMModuleAnchorSource = 0;
} // namespace tidy
} // namespace clang

View File

@@ -0,0 +1,66 @@
//===--- TwineLocalCheck.cpp - clang-tidy ---------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "TwineLocalCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace llvm {
void TwineLocalCheck::registerMatchers(MatchFinder *Finder) {
auto TwineType =
qualType(hasDeclaration(recordDecl(hasName("::llvm::Twine"))));
Finder->addMatcher(varDecl(hasType(TwineType)).bind("variable"), this);
}
void TwineLocalCheck::check(const MatchFinder::MatchResult &Result) {
const auto *VD = Result.Nodes.getNodeAs<VarDecl>("variable");
auto Diag = diag(VD->getLocation(),
"twine variables are prone to use-after-free bugs");
// If this VarDecl has an initializer try to fix it.
if (VD->hasInit()) {
// Peel away implicit constructors and casts so we can see the actual type
// of the initializer.
const Expr *C = VD->getInit()->IgnoreImplicit();
while (isa<CXXConstructExpr>(C)) {
if (cast<CXXConstructExpr>(C)->getNumArgs() == 0)
break;
C = cast<CXXConstructExpr>(C)->getArg(0)->IgnoreParenImpCasts();
}
SourceRange TypeRange =
VD->getTypeSourceInfo()->getTypeLoc().getSourceRange();
// A real Twine, turn it into a std::string.
if (VD->getType()->getCanonicalTypeUnqualified() ==
C->getType()->getCanonicalTypeUnqualified()) {
SourceLocation EndLoc = Lexer::getLocForEndOfToken(
VD->getInit()->getLocEnd(), 0, *Result.SourceManager, getLangOpts());
Diag << FixItHint::CreateReplacement(TypeRange, "std::string")
<< FixItHint::CreateInsertion(VD->getInit()->getLocStart(), "(")
<< FixItHint::CreateInsertion(EndLoc, ").str()");
} else {
// Just an implicit conversion. Insert the real type.
Diag << FixItHint::CreateReplacement(
TypeRange,
C->getType().getAsString(Result.Context->getPrintingPolicy()));
}
}
}
} // namespace llvm
} // namespace tidy
} // namespace clang

View File

@@ -0,0 +1,33 @@
//===--- TwineLocalCheck.h - clang-tidy -------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_TWINE_LOCAL_CHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_TWINE_LOCAL_CHECK_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace llvm {
/// Looks for local `Twine` variables which are prone to use after frees and
/// should be generally avoided.
class TwineLocalCheck : public ClangTidyCheck {
public:
TwineLocalCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace llvm
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_TWINE_LOCAL_CHECK_H