Commit 249f8f5d authored by Jenkins CI's avatar Jenkins CI
Browse files

Merge remote-tracking branch 'downstream/EPI' into EPI

parents 5106b116 981af4f4

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.
Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,-misc-non-private-member-variables-in-classes,readability-identifier-naming'
Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,-misc-non-private-member-variables-in-classes,-misc-no-recursion,readability-identifier-naming'
CheckOptions:
- key: readability-identifier-naming.ClassCase
value: CamelCase
......
......@@ -40,3 +40,6 @@ d8f0e6caa91e230a486c948ab643174e40bdf215
# Wiped out some non-ascii characters that snuck into the copyright.
5b08a8a43254ed30bd953e869b0fd9fc1e8b82d0
# Use C++11 default member initializers in LLDB. NFC.
9494c510af56d9c8593ab69017dcaa232210b235
......@@ -22,6 +22,11 @@
#
# Please keep this file sorted.
<i@maskray.me> <maskray@google.com>
<qiucofan@cn.ibm.com> <qiucf@cn.ibm.com>
<rnk@google.com> <reid@kleckner.net>
<thakis@chromium.org> <nicolasweber@gmx.de>
<i@maskray.me> <maskray@google.com>
Jon Roelofs <jonathan_roelofs@apple.com> Jon Roelofs <jroelofs@jroelofs.com>
Jon Roelofs <jonathan_roelofs@apple.com> Jonathan Roelofs <jonathan@codesourcery.com>
Jon Roelofs <jonathan_roelofs@apple.com> Jonathan Roelofs <jroelofs@jroelofs.com>
Martin Storsjö <martin@martin.st>
......@@ -35,6 +35,8 @@ auto hasAnyListedName(const std::string &Names) {
NarrowingConversionsCheck::NarrowingConversionsCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
WarnOnIntegerNarrowingConversion(
Options.get("WarnOnIntegerNarrowingConversion", true)),
WarnOnFloatingPointNarrowingConversion(
Options.get("WarnOnFloatingPointNarrowingConversion", true)),
WarnWithinTemplateInstantiation(
......@@ -45,6 +47,8 @@ NarrowingConversionsCheck::NarrowingConversionsCheck(StringRef Name,
void NarrowingConversionsCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "WarnOnIntegerNarrowingConversion",
WarnOnIntegerNarrowingConversion);
Options.store(Opts, "WarnOnFloatingPointNarrowingConversion",
WarnOnFloatingPointNarrowingConversion);
Options.store(Opts, "WarnWithinTemplateInstantiation",
......@@ -294,34 +298,37 @@ void NarrowingConversionsCheck::handleIntegralCast(const ASTContext &Context,
SourceLocation SourceLoc,
const Expr &Lhs,
const Expr &Rhs) {
const BuiltinType *ToType = getBuiltinType(Lhs);
// From [conv.integral]p7.3.8:
// Conversions to unsigned integer is well defined so no warning is issued.
// "The resulting value is the smallest unsigned value equal to the source
// value modulo 2^n where n is the number of bits used to represent the
// destination type."
if (ToType->isUnsignedInteger())
return;
const BuiltinType *FromType = getBuiltinType(Rhs);
// With this option, we don't warn on conversions that have equivalent width
// in bits. eg. uint32 <-> int32.
if (!WarnOnEquivalentBitWidth) {
uint64_t FromTypeSize = Context.getTypeSize(FromType);
uint64_t ToTypeSize = Context.getTypeSize(ToType);
if (FromTypeSize == ToTypeSize)
if (WarnOnIntegerNarrowingConversion) {
const BuiltinType *ToType = getBuiltinType(Lhs);
// From [conv.integral]p7.3.8:
// Conversions to unsigned integer is well defined so no warning is issued.
// "The resulting value is the smallest unsigned value equal to the source
// value modulo 2^n where n is the number of bits used to represent the
// destination type."
if (ToType->isUnsignedInteger())
return;
}
const BuiltinType *FromType = getBuiltinType(Rhs);
llvm::APSInt IntegerConstant;
if (getIntegerConstantExprValue(Context, Rhs, IntegerConstant)) {
if (!isWideEnoughToHold(Context, IntegerConstant, *ToType))
diagNarrowIntegerConstantToSignedInt(SourceLoc, Lhs, Rhs, IntegerConstant,
Context.getTypeSize(FromType));
return;
// With this option, we don't warn on conversions that have equivalent width
// in bits. eg. uint32 <-> int32.
if (!WarnOnEquivalentBitWidth) {
uint64_t FromTypeSize = Context.getTypeSize(FromType);
uint64_t ToTypeSize = Context.getTypeSize(ToType);
if (FromTypeSize == ToTypeSize)
return;
}
llvm::APSInt IntegerConstant;
if (getIntegerConstantExprValue(Context, Rhs, IntegerConstant)) {
if (!isWideEnoughToHold(Context, IntegerConstant, *ToType))
diagNarrowIntegerConstantToSignedInt(SourceLoc, Lhs, Rhs,
IntegerConstant,
Context.getTypeSize(FromType));
return;
}
if (!isWideEnoughToHold(Context, *FromType, *ToType))
diagNarrowTypeToSignedInt(SourceLoc, Lhs, Rhs);
}
if (!isWideEnoughToHold(Context, *FromType, *ToType))
diagNarrowTypeToSignedInt(SourceLoc, Lhs, Rhs);
}
void NarrowingConversionsCheck::handleIntegralToBoolean(
......
......@@ -93,6 +93,7 @@ private:
void handleBinaryOperator(const ASTContext &Context,
const BinaryOperator &Op);
const bool WarnOnIntegerNarrowingConversion;
const bool WarnOnFloatingPointNarrowingConversion;
const bool WarnWithinTemplateInstantiation;
const bool WarnOnEquivalentBitWidth;
......
......@@ -124,7 +124,7 @@ void UniqueptrResetReleaseCheck::check(const MatchFinder::MatchResult &Result) {
AssignmentText = " = std::move(*";
TrailingText = ")";
NeedsUtilityInclude = true;
} else if (!Right->isRValue()) {
} else if (!Right->isPRValue()) {
AssignmentText = " = std::move(";
TrailingText = ")";
NeedsUtilityInclude = true;
......
......@@ -429,7 +429,7 @@ static bool usagesAreConst(ASTContext *Context, const UsageResult &Usages) {
/// by reference.
static bool usagesReturnRValues(const UsageResult &Usages) {
for (const auto &U : Usages) {
if (U.Expression && !U.Expression->isRValue())
if (U.Expression && !U.Expression->isPRValue())
return false;
}
return true;
......
......@@ -7,9 +7,9 @@
//===----------------------------------------------------------------------===//
#include "UnnecessaryCopyInitialization.h"
#include "../utils/DeclRefExprUtils.h"
#include "../utils/FixItHintUtils.h"
#include "../utils/LexerUtils.h"
#include "../utils/Matchers.h"
#include "../utils/OptionsUtils.h"
#include "clang/Basic/Diagnostic.h"
......@@ -21,6 +21,7 @@ namespace {
using namespace ::clang::ast_matchers;
using llvm::StringRef;
using utils::decl_ref_expr::allDeclRefExprs;
using utils::decl_ref_expr::isOnlyUsedAsConst;
static constexpr StringRef ObjectArgId = "objectArg";
......@@ -37,6 +38,19 @@ void recordFixes(const VarDecl &Var, ASTContext &Context,
}
}
void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
DiagnosticBuilder &Diagnostic) {
// Attempt to remove the whole line until the next non-comment token.
auto Tok = utils::lexer::findNextTokenSkippingComments(
Stmt.getEndLoc(), Context.getSourceManager(), Context.getLangOpts());
if (Tok) {
Diagnostic << FixItHint::CreateRemoval(SourceRange(
Stmt.getBeginLoc(), Tok->getLocation().getLocWithOffset(-1)));
} else {
Diagnostic << FixItHint::CreateRemoval(Stmt.getSourceRange());
}
}
AST_MATCHER_FUNCTION(StatementMatcher, isConstRefReturningMethodCall) {
// Match method call expressions where the `this` argument is only used as
// const, this will be checked in `check()` part. This returned const
......@@ -86,7 +100,7 @@ static bool isInitializingVariableImmutable(const VarDecl &InitializingVar,
if (!isOnlyUsedAsConst(InitializingVar, BlockStmt, Context))
return false;
QualType T = InitializingVar.getType();
QualType T = InitializingVar.getType().getCanonicalType();
// The variable is a value type and we know it is only used as const. Safe
// to reference it and avoid the copy.
if (!isa<ReferenceType, PointerType>(T))
......@@ -118,6 +132,11 @@ static bool isInitializingVariableImmutable(const VarDecl &InitializingVar,
return false;
}
bool isVariableUnused(const VarDecl &Var, const Stmt &BlockStmt,
ASTContext &Context) {
return allDeclRefExprs(Var, BlockStmt, Context).empty();
}
} // namespace
UnnecessaryCopyInitialization::UnnecessaryCopyInitialization(
......@@ -169,14 +188,13 @@ void UnnecessaryCopyInitialization::check(
const auto *ObjectArg = Result.Nodes.getNodeAs<VarDecl>(ObjectArgId);
const auto *BlockStmt = Result.Nodes.getNodeAs<Stmt>("blockStmt");
const auto *CtorCall = Result.Nodes.getNodeAs<CXXConstructExpr>("ctorCall");
const auto *Stmt = Result.Nodes.getNodeAs<DeclStmt>("declStmt");
TraversalKindScope RAII(*Result.Context, TK_AsIs);
// Do not propose fixes if the DeclStmt has multiple VarDecls or in macros
// since we cannot place them correctly.
bool IssueFix =
Result.Nodes.getNodeAs<DeclStmt>("declStmt")->isSingleDecl() &&
!NewVar->getLocation().isMacroID();
bool IssueFix = Stmt->isSingleDecl() && !NewVar->getLocation().isMacroID();
// A constructor that looks like T(const T& t, bool arg = false) counts as a
// copy only when it is called with default arguments for the arguments after
......@@ -186,47 +204,68 @@ void UnnecessaryCopyInitialization::check(
return;
if (OldVar == nullptr) {
handleCopyFromMethodReturn(*NewVar, *BlockStmt, IssueFix, ObjectArg,
handleCopyFromMethodReturn(*NewVar, *BlockStmt, *Stmt, IssueFix, ObjectArg,
*Result.Context);
} else {
handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, IssueFix,
handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, *Stmt, IssueFix,
*Result.Context);
}
}
void UnnecessaryCopyInitialization::handleCopyFromMethodReturn(
const VarDecl &Var, const Stmt &BlockStmt, bool IssueFix,
const VarDecl *ObjectArg, ASTContext &Context) {
const VarDecl &Var, const Stmt &BlockStmt, const DeclStmt &Stmt,
bool IssueFix, const VarDecl *ObjectArg, ASTContext &Context) {
bool IsConstQualified = Var.getType().isConstQualified();
if (!IsConstQualified && !isOnlyUsedAsConst(Var, BlockStmt, Context))
return;
if (ObjectArg != nullptr &&
!isInitializingVariableImmutable(*ObjectArg, BlockStmt, Context))
return;
auto Diagnostic =
diag(Var.getLocation(),
"the %select{|const qualified }0variable %1 is copy-constructed "
"from a const reference%select{ but is only used as const "
"reference|}0; consider making it a const reference")
<< IsConstQualified << &Var;
if (IssueFix)
recordFixes(Var, Context, Diagnostic);
if (isVariableUnused(Var, BlockStmt, Context)) {
auto Diagnostic =
diag(Var.getLocation(),
"the %select{|const qualified }0variable %1 is copy-constructed "
"from a const reference but is never used; consider "
"removing the statement")
<< IsConstQualified << &Var;
if (IssueFix)
recordRemoval(Stmt, Context, Diagnostic);
} else {
auto Diagnostic =
diag(Var.getLocation(),
"the %select{|const qualified }0variable %1 is copy-constructed "
"from a const reference%select{ but is only used as const "
"reference|}0; consider making it a const reference")
<< IsConstQualified << &Var;
if (IssueFix)
recordFixes(Var, Context, Diagnostic);
}
}
void UnnecessaryCopyInitialization::handleCopyFromLocalVar(
const VarDecl &NewVar, const VarDecl &OldVar, const Stmt &BlockStmt,
bool IssueFix, ASTContext &Context) {
const DeclStmt &Stmt, bool IssueFix, ASTContext &Context) {
if (!isOnlyUsedAsConst(NewVar, BlockStmt, Context) ||
!isInitializingVariableImmutable(OldVar, BlockStmt, Context))
return;
auto Diagnostic = diag(NewVar.getLocation(),
"local copy %0 of the variable %1 is never modified; "
"consider avoiding the copy")
<< &NewVar << &OldVar;
if (IssueFix)
recordFixes(NewVar, Context, Diagnostic);
if (isVariableUnused(NewVar, BlockStmt, Context)) {
auto Diagnostic = diag(NewVar.getLocation(),
"local copy %0 of the variable %1 is never modified "
"and never used; "
"consider removing the statement")
<< &NewVar << &OldVar;
if (IssueFix)
recordRemoval(Stmt, Context, Diagnostic);
} else {
auto Diagnostic =
diag(NewVar.getLocation(),
"local copy %0 of the variable %1 is never modified; "
"consider avoiding the copy")
<< &NewVar << &OldVar;
if (IssueFix)
recordFixes(NewVar, Context, Diagnostic);
}
}
void UnnecessaryCopyInitialization::storeOptions(
......
......@@ -35,11 +35,12 @@ public:
private:
void handleCopyFromMethodReturn(const VarDecl &Var, const Stmt &BlockStmt,
bool IssueFix, const VarDecl *ObjectArg,
const DeclStmt &Stmt, bool IssueFix,
const VarDecl *ObjectArg,
ASTContext &Context);
void handleCopyFromLocalVar(const VarDecl &NewVar, const VarDecl &OldVar,
const Stmt &BlockStmt, bool IssueFix,
ASTContext &Context);
const Stmt &BlockStmt, const DeclStmt &Stmt,
bool IssueFix, ASTContext &Context);
const std::vector<std::string> AllowedTypes;
};
......
......@@ -181,6 +181,9 @@ public:
for (const UsingShadowDecl *S : UD->shadows())
add(S->getUnderlyingDecl(), Flags);
Flags |= Rel::Alias; // continue with the alias.
} else if (const UsingEnumDecl *UED = dyn_cast<UsingEnumDecl>(D)) {
add(UED->getEnumDecl(), Flags);
Flags |= Rel::Alias; // continue with the alias.
} else if (const auto *NAD = dyn_cast<NamespaceAliasDecl>(D)) {
add(NAD->getUnderlyingDecl(), Flags | Rel::Underlying);
Flags |= Rel::Alias; // continue with the alias
......@@ -193,9 +196,9 @@ public:
}
Flags |= Rel::Alias; // continue with the alias
} else if (const UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) {
// Include the using decl, but don't traverse it. This may end up
// Include the Introducing decl, but don't traverse it. This may end up
// including *all* shadows, which we don't want.
report(USD->getUsingDecl(), Flags | Rel::Alias);
report(USD->getIntroducer(), Flags | Rel::Alias);
// Shadow decls are synthetic and not themselves interesting.
// Record the underlying decl instead, if allowed.
D = USD->getTargetDecl();
......
......@@ -67,5 +67,15 @@ SymbolSlab SymbolSlab::Builder::build() && {
return SymbolSlab(std::move(NewArena), std::move(SortedSymbols));
}
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolSlab &Slab) {
OS << "{";
llvm::StringRef Sep = "";
for (const auto &S : Slab) {
OS << Sep << S;
Sep = ", ";
}
OS << "}";
return OS;
}
} // namespace clangd
} // namespace clang
......@@ -233,6 +233,8 @@ private:
std::vector<Symbol> Symbols; // Sorted by SymbolID to allow lookup.
};
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolSlab &Slab);
} // namespace clangd
} // namespace clang
......
......@@ -35,7 +35,7 @@ can easily uninstall gRPC or use different versions.
```bash
# Get source code.
$ git clone -b v1.33.2 https://github.com/grpc/grpc
$ git clone -b v1.36.3 https://github.com/grpc/grpc
$ cd grpc
$ git submodule update --init
# Choose directory where you want gRPC installation to live.
......
......@@ -193,10 +193,15 @@ public:
// Run AST-based features at each token in the file.
void testLocationFeatures(
llvm::function_ref<bool(const Position &)> ShouldCheckLine) {
llvm::function_ref<bool(const Position &)> ShouldCheckLine,
const bool EnableCodeCompletion) {
log("Testing features at each token (may be slow in large files)");
auto &SM = AST->getSourceManager();
auto SpelledTokens = AST->getTokens().spelledTokens(SM.getMainFileID());
CodeCompleteOptions CCOpts = Opts.CodeComplete;
CCOpts.Index = &Index;
for (const auto &Tok : SpelledTokens) {
unsigned Start = AST->getSourceManager().getFileOffset(Tok.location());
unsigned End = Start + Tok.length();
......@@ -233,8 +238,12 @@ public:
auto Hover = getHover(*AST, Pos, Style, &Index);
vlog(" hover: {0}", Hover.hasValue());
// FIXME: it'd be nice to include code completion, but it's too slow.
// Maybe in combination with a line restriction?
if (EnableCodeCompletion) {
Position EndPos = offsetToPosition(Inputs.Contents, End);
auto CC = codeComplete(File, EndPos, Preamble.get(), Inputs, CCOpts);
vlog(" code completion: {0}",
CC.Completions.empty() ? "<empty>" : CC.Completions[0].Name);
}
}
}
};
......@@ -243,7 +252,8 @@ public:
bool check(llvm::StringRef File,
llvm::function_ref<bool(const Position &)> ShouldCheckLine,
const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts) {
const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts,
bool EnableCodeCompletion) {
llvm::SmallString<0> FakeFile;
llvm::Optional<std::string> Contents;
if (File.empty()) {
......@@ -267,7 +277,7 @@ bool check(llvm::StringRef File,
if (!C.buildCommand(TFS) || !C.buildInvocation(TFS, Contents) ||
!C.buildAST())
return false;
C.testLocationFeatures(ShouldCheckLine);
C.testLocationFeatures(ShouldCheckLine, EnableCodeCompletion);
log("All checks completed, {0} errors", C.ErrCount);
return C.ErrCount == 0;
......
......@@ -62,7 +62,8 @@ namespace clangd {
// Implemented in Check.cpp.
bool check(const llvm::StringRef File,
llvm::function_ref<bool(const Position &)> ShouldCheckLine,
const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts);
const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts,
bool EnableCodeCompletion);
namespace {
......@@ -929,7 +930,11 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
uint32_t Line = Pos.line + 1; // Position::line is 0-based.
return Line >= Begin && Line <= End;
};
return check(Path, ShouldCheckLine, TFS, Opts)
// For now code completion is enabled any time the range is limited via
// --check-lines. If it turns out to be to slow, we can introduce a
// dedicated flag for that instead.
return check(Path, ShouldCheckLine, TFS, Opts,
/*EnableCodeCompletion=*/!CheckFileLines.empty())
? 0
: static_cast<int>(ErrorResultCode::CheckFailed);
}
......
......@@ -659,10 +659,11 @@ TEST(SelectionTest, CreateAll) {
AST.getASTContext(), AST.getTokens(), Test.point("ambiguous"),
Test.point("ambiguous"), [&](SelectionTree T) {
// Expect to see the right-biased tree first.
if (Seen == 0)
if (Seen == 0) {
EXPECT_EQ("BinaryOperator", nodeKind(T.commonAncestor()));
else if (Seen == 1)
} else if (Seen == 1) {
EXPECT_EQ("IntegerLiteral", nodeKind(T.commonAncestor()));
}
++Seen;
return false;
});
......
......@@ -17,7 +17,9 @@
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/Utils.h"
#include "llvm/ADT/ScopeExit.h"
#include "gtest/gtest.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
namespace clang {
namespace clangd {
......@@ -69,14 +71,19 @@ ParseInputs TestTU::inputs(MockFS &FS) const {
void initializeModuleCache(CompilerInvocation &CI) {
llvm::SmallString<128> ModuleCachePath;
ASSERT_FALSE(
llvm::sys::fs::createUniqueDirectory("module-cache", ModuleCachePath));
if (llvm::sys::fs::createUniqueDirectory("module-cache", ModuleCachePath)) {
llvm::errs() << "Failed to create temp directory for module-cache";
std::abort();
}
CI.getHeaderSearchOpts().ModuleCachePath = ModuleCachePath.c_str();
}
void deleteModuleCache(const std::string ModuleCachePath) {
if (!ModuleCachePath.empty()) {
ASSERT_FALSE(llvm::sys::fs::remove_directories(ModuleCachePath));
if (llvm::sys::fs::remove_directories(ModuleCachePath)) {
llvm::errs() << "Failed to delete temp directory for module-cache";
std::abort();
}
}
}
......@@ -112,14 +119,11 @@ ParsedAST TestTU::build() const {
auto AST = ParsedAST::build(testPath(Filename), Inputs, std::move(CI),
Diags.take(), Preamble);
if (!AST.hasValue()) {
ADD_FAILURE() << "Failed to build code:\n" << Code;
llvm_unreachable("Failed to build TestTU!");
}
if (!AST->getDiagnostics()) {
ADD_FAILURE() << "TestTU should always build an AST with a fresh Preamble"
<< Code;
return std::move(*AST);
llvm::errs() << "Failed to build code:\n" << Code;
std::abort();
}
assert(AST->getDiagnostics() &&
"TestTU should always build an AST with a fresh Preamble");
// Check for error diagnostics and report gtest failures (unless expected).
// This guards against accidental syntax errors silently subverting tests.
// error-ok is awfully primitive - using clang -verify would be nicer.
......@@ -138,11 +142,11 @@ ParsedAST TestTU::build() const {
// We always build AST with a fresh preamble in TestTU.
for (const auto &D : *AST->getDiagnostics())
if (D.Severity >= DiagnosticsEngine::Error) {
ADD_FAILURE()
llvm::errs()
<< "TestTU failed to build (suppress with /*error-ok*/): \n"
<< D << "\n\nFor code:\n"
<< Code;
break; // Just report first error for simplicity.
std::abort(); // Stop after first error for simplicity.
}
}
return std::move(*AST);
......@@ -176,16 +180,16 @@ const Symbol &findSymbol(const SymbolSlab &Slab, llvm::StringRef QName) {
if (QName != (S.Scope + S.Name).str())
continue;
if (Result) {
ADD_FAILURE() << "Multiple symbols named " << QName << ":\n"
<< *Result << "\n---\n"
<< S;
llvm::errs() << "Multiple symbols named " << QName << ":\n"
<< *Result << "\n---\n"
<< S;
assert(false && "QName is not unique");
}
Result = &S;
}
if (!Result) {
ADD_FAILURE() << "No symbol named " << QName << " in "
<< ::testing::PrintToString(Slab);
llvm::errs() << "No symbol named " << QName << " in "
<< llvm::to_string(Slab);
assert(false && "No symbol with QName");
}
return *Result;
......@@ -225,7 +229,7 @@ const NamedDecl &findDecl(ParsedAST &AST,
Visitor.F = Filter;
Visitor.TraverseDecl(AST.getASTContext().getTranslationUnitDecl());
if (Visitor.Decls.size() != 1) {
ADD_FAILURE() << Visitor.Decls.size() << " symbols matched.";
llvm::errs() << Visitor.Decls.size() << " symbols matched.";
assert(Visitor.Decls.size() == 1);
}
return *Visitor.Decls.front();
......
......@@ -13,7 +13,8 @@ Guidelines, corresponding to rule ES.46. See
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es46-avoid-lossy-narrowing-truncating-arithmetic-conversions.
We enforce only part of the guideline, more specifically, we flag narrowing conversions from:
- an integer to a narrower integer (e.g. ``char`` to ``unsigned char``),
- an integer to a narrower integer (e.g. ``char`` to ``unsigned char``)
if WarnOnIntegerNarrowingConversion Option is set,
- an integer to a narrower floating-point (e.g. ``uint64_t`` to ``float``),