Skip to content

Commit

Permalink
Merged main:ae8f4b2178c4 into amd-gfx:050a073d7e98
Browse files Browse the repository at this point in the history
Local branch amd-gfx 050a073 Merged main:0955d8df0635 into amd-gfx:e6226f754f5c
Remote branch main ae8f4b2 [AMDGPU] Folding of FI operand with flat scratch
  • Loading branch information
Sw authored and Sw committed Dec 22, 2020
2 parents 050a073 + ae8f4b2 commit 52b1011
Show file tree
Hide file tree
Showing 137 changed files with 2,434 additions and 1,319 deletions.
183 changes: 148 additions & 35 deletions clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,77 @@
using namespace clang::ast_matchers;

namespace clang {
namespace ast_matchers {
AST_POLYMORPHIC_MATCHER_P2(hasAnyArgumentWithParam,
AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
CXXConstructExpr),
internal::Matcher<Expr>, ArgMatcher,
internal::Matcher<ParmVarDecl>, ParamMatcher) {
BoundNodesTreeBuilder Result;
// The first argument of an overloaded member operator is the implicit object
// argument of the method which should not be matched against a parameter, so
// we skip over it here.
BoundNodesTreeBuilder Matches;
unsigned ArgIndex = cxxOperatorCallExpr(callee(cxxMethodDecl()))
.matches(Node, Finder, &Matches)
? 1
: 0;
int ParamIndex = 0;
for (; ArgIndex < Node.getNumArgs(); ++ArgIndex) {
BoundNodesTreeBuilder ArgMatches(*Builder);
if (ArgMatcher.matches(*(Node.getArg(ArgIndex)->IgnoreParenCasts()), Finder,
&ArgMatches)) {
BoundNodesTreeBuilder ParamMatches(ArgMatches);
if (expr(anyOf(cxxConstructExpr(hasDeclaration(cxxConstructorDecl(
hasParameter(ParamIndex, ParamMatcher)))),
callExpr(callee(functionDecl(
hasParameter(ParamIndex, ParamMatcher))))))
.matches(Node, Finder, &ParamMatches)) {
Result.addMatch(ParamMatches);
*Builder = std::move(Result);
return true;
}
}
++ParamIndex;
}
return false;
}

AST_MATCHER(Expr, usedInBooleanContext) {
const char *ExprName = "__booleanContextExpr";
auto Result =
expr(expr().bind(ExprName),
anyOf(hasParent(varDecl(hasType(booleanType()))),
hasParent(cxxConstructorDecl(
hasAnyConstructorInitializer(cxxCtorInitializer(
withInitializer(expr(equalsBoundNode(ExprName))),
forField(hasType(booleanType())))))),
hasParent(fieldDecl(hasType(booleanType()))),
hasParent(stmt(anyOf(
explicitCastExpr(hasDestinationType(booleanType())),
ifStmt(hasCondition(expr(equalsBoundNode(ExprName)))),
doStmt(hasCondition(expr(equalsBoundNode(ExprName)))),
whileStmt(hasCondition(expr(equalsBoundNode(ExprName)))),
forStmt(hasCondition(expr(equalsBoundNode(ExprName)))),
conditionalOperator(
hasCondition(expr(equalsBoundNode(ExprName)))),
parenListExpr(hasParent(varDecl(hasType(booleanType())))),
parenExpr(hasParent(
explicitCastExpr(hasDestinationType(booleanType())))),
returnStmt(forFunction(returns(booleanType()))),
cxxUnresolvedConstructExpr(hasType(booleanType())),
callExpr(hasAnyArgumentWithParam(
expr(equalsBoundNode(ExprName)),
parmVarDecl(hasType(booleanType())))),
binaryOperator(hasAnyOperatorName("&&", "||")),
unaryOperator(hasOperatorName("!")).bind("NegOnSize"))))))
.matches(Node, Finder, Builder);
Builder->removeBindings([ExprName](const BoundNodesMap &Nodes) {
return Nodes.getNode(ExprName).getNodeKind().isNone();
});
return Result;
}
} // namespace ast_matchers
namespace tidy {
namespace readability {

Expand All @@ -26,18 +97,27 @@ ContainerSizeEmptyCheck::ContainerSizeEmptyCheck(StringRef Name,
: ClangTidyCheck(Name, Context) {}

void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) {
const auto ValidContainer = qualType(hasUnqualifiedDesugaredType(
recordType(hasDeclaration(cxxRecordDecl(isSameOrDerivedFrom(
namedDecl(
has(cxxMethodDecl(
isConst(), parameterCountIs(0), isPublic(),
hasName("size"),
returns(qualType(isInteger(), unless(booleanType()))))
.bind("size")),
has(cxxMethodDecl(isConst(), parameterCountIs(0), isPublic(),
hasName("empty"), returns(booleanType()))
.bind("empty")))
.bind("container")))))));
const auto ValidContainerRecord = cxxRecordDecl(isSameOrDerivedFrom(
namedDecl(
has(cxxMethodDecl(isConst(), parameterCountIs(0), isPublic(),
hasName("size"),
returns(qualType(isInteger(), unless(booleanType()),
unless(elaboratedType()))))
.bind("size")),
has(cxxMethodDecl(isConst(), parameterCountIs(0), isPublic(),
hasName("empty"), returns(booleanType()))
.bind("empty")))
.bind("container")));

const auto ValidContainerNonTemplateType =
qualType(hasUnqualifiedDesugaredType(
recordType(hasDeclaration(ValidContainerRecord))));
const auto ValidContainerTemplateType =
qualType(hasUnqualifiedDesugaredType(templateSpecializationType(
hasDeclaration(classTemplateDecl(has(ValidContainerRecord))))));

const auto ValidContainer = qualType(
anyOf(ValidContainerNonTemplateType, ValidContainerTemplateType));

const auto WrongUse = traverse(
TK_AsIs,
Expand All @@ -52,18 +132,34 @@ void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) {
anyOf(hasParent(
unaryOperator(hasOperatorName("!")).bind("NegOnSize")),
anything()))),
hasParent(explicitCastExpr(hasDestinationType(booleanType())))));
usedInBooleanContext()));

Finder->addMatcher(
cxxMemberCallExpr(on(expr(anyOf(hasType(ValidContainer),
cxxMemberCallExpr(unless(isInTemplateInstantiation()),
on(expr(anyOf(hasType(ValidContainer),
hasType(pointsTo(ValidContainer)),
hasType(references(ValidContainer))))),
hasType(references(ValidContainer))))
.bind("MemberCallObject")),
callee(cxxMethodDecl(hasName("size"))), WrongUse,
unless(hasAncestor(cxxMethodDecl(
ofClass(equalsBoundNode("container"))))))
.bind("SizeCallExpr"),
this);

Finder->addMatcher(
callExpr(has(cxxDependentScopeMemberExpr(
hasObjectExpression(
expr(anyOf(hasType(ValidContainer),
hasType(pointsTo(ValidContainer)),
hasType(references(ValidContainer))))
.bind("MemberCallObject")),
hasMemberName("size"))),
WrongUse,
unless(hasAncestor(
cxxMethodDecl(ofClass(equalsBoundNode("container"))))))
.bind("SizeCallExpr"),
this);

// Empty constructor matcher.
const auto DefaultConstructor = cxxConstructExpr(
hasDeclaration(cxxConstructorDecl(isDefaultConstructor())));
Expand All @@ -72,12 +168,11 @@ void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) {
ignoringImpCasts(stringLiteral(hasSize(0))),
ignoringImpCasts(cxxBindTemporaryExpr(has(DefaultConstructor))),
ignoringImplicit(DefaultConstructor),
cxxConstructExpr(
hasDeclaration(cxxConstructorDecl(isCopyConstructor())),
has(expr(ignoringImpCasts(DefaultConstructor)))),
cxxConstructExpr(
hasDeclaration(cxxConstructorDecl(isMoveConstructor())),
has(expr(ignoringImpCasts(DefaultConstructor)))));
cxxConstructExpr(hasDeclaration(cxxConstructorDecl(isCopyConstructor())),
has(expr(ignoringImpCasts(DefaultConstructor)))),
cxxConstructExpr(hasDeclaration(cxxConstructorDecl(isMoveConstructor())),
has(expr(ignoringImpCasts(DefaultConstructor)))),
cxxUnresolvedConstructExpr(argumentCountIs(0)));
// Match the object being compared.
const auto STLArg =
anyOf(unaryOperator(
Expand All @@ -87,31 +182,41 @@ void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) {
expr(hasType(ValidContainer)).bind("STLObject"));
Finder->addMatcher(
cxxOperatorCallExpr(
unless(isInTemplateInstantiation()),
hasAnyOverloadedOperatorName("==", "!="),
anyOf(allOf(hasArgument(0, WrongComparend), hasArgument(1, STLArg)),
allOf(hasArgument(0, STLArg), hasArgument(1, WrongComparend))),
unless(hasAncestor(
cxxMethodDecl(ofClass(equalsBoundNode("container"))))))
.bind("BinCmp"),
this);
Finder->addMatcher(
binaryOperator(hasAnyOperatorName("==", "!="),
anyOf(allOf(hasLHS(WrongComparend), hasRHS(STLArg)),
allOf(hasLHS(STLArg), hasRHS(WrongComparend))),
unless(hasAncestor(
cxxMethodDecl(ofClass(equalsBoundNode("container"))))))
.bind("BinCmp"),
this);
}

void ContainerSizeEmptyCheck::check(const MatchFinder::MatchResult &Result) {
const auto *MemberCall =
Result.Nodes.getNodeAs<CXXMemberCallExpr>("SizeCallExpr");
const auto *MemberCall = Result.Nodes.getNodeAs<Expr>("SizeCallExpr");
const auto *MemberCallObject =
Result.Nodes.getNodeAs<Expr>("MemberCallObject");
const auto *BinCmp = Result.Nodes.getNodeAs<CXXOperatorCallExpr>("BinCmp");
const auto *BinCmpTempl = Result.Nodes.getNodeAs<BinaryOperator>("BinCmp");
const auto *BinaryOp = Result.Nodes.getNodeAs<BinaryOperator>("SizeBinaryOp");
const auto *Pointee = Result.Nodes.getNodeAs<Expr>("Pointee");
const auto *E =
MemberCall
? MemberCall->getImplicitObjectArgument()
MemberCallObject
? MemberCallObject
: (Pointee ? Pointee : Result.Nodes.getNodeAs<Expr>("STLObject"));
FixItHint Hint;
std::string ReplacementText = std::string(
Lexer::getSourceText(CharSourceRange::getTokenRange(E->getSourceRange()),
*Result.SourceManager, getLangOpts()));
if (BinCmp && IsBinaryOrTernary(E)) {
// Not just a DeclRefExpr, so parenthesize to be on the safe side.
if (IsBinaryOrTernary(E) || isa<UnaryOperator>(E)) {
ReplacementText = "(" + ReplacementText + ")";
}
if (E->getType()->isPointerType())
Expand All @@ -125,7 +230,13 @@ void ContainerSizeEmptyCheck::check(const MatchFinder::MatchResult &Result) {
}
Hint =
FixItHint::CreateReplacement(BinCmp->getSourceRange(), ReplacementText);
} else if (BinaryOp) { // Determine the correct transformation.
} else if (BinCmpTempl) {
if (BinCmpTempl->getOpcode() == BinaryOperatorKind::BO_NE) {
ReplacementText = "!" + ReplacementText;
}
Hint = FixItHint::CreateReplacement(BinCmpTempl->getSourceRange(),
ReplacementText);
} else if (BinaryOp) { // Determine the correct transformation.
bool Negation = false;
const bool ContainerIsLHS =
!llvm::isa<IntegerLiteral>(BinaryOp->getLHS()->IgnoreImpCasts());
Expand Down Expand Up @@ -195,15 +306,17 @@ void ContainerSizeEmptyCheck::check(const MatchFinder::MatchResult &Result) {
"!" + ReplacementText);
}

if (MemberCall) {
diag(MemberCall->getBeginLoc(),
"the 'empty' method should be used to check "
"for emptiness instead of 'size'")
auto WarnLoc = MemberCall ? MemberCall->getBeginLoc() : SourceLocation{};

if (WarnLoc.isValid()) {
diag(WarnLoc, "the 'empty' method should be used to check "
"for emptiness instead of 'size'")
<< Hint;
} else {
diag(BinCmp->getBeginLoc(),
"the 'empty' method should be used to check "
"for emptiness instead of comparing to an empty object")
WarnLoc = BinCmpTempl ? BinCmpTempl->getBeginLoc()
: (BinCmp ? BinCmp->getBeginLoc() : SourceLocation{});
diag(WarnLoc, "the 'empty' method should be used to check "
"for emptiness instead of comparing to an empty object")
<< Hint;
}

Expand Down
1 change: 0 additions & 1 deletion clang-tools-extra/clangd/DumpAST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ class DumpVisitor : public RecursiveASTVisitor<DumpVisitor> {
TEMPLATE_ARGUMENT_KIND(Declaration);
TEMPLATE_ARGUMENT_KIND(Template);
TEMPLATE_ARGUMENT_KIND(TemplateExpansion);
TEMPLATE_ARGUMENT_KIND(UncommonValue);
#undef TEMPLATE_ARGUMENT_KIND
}
llvm_unreachable("Unhandled ArgKind enum");
Expand Down
1 change: 0 additions & 1 deletion clang-tools-extra/clangd/FindTarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1069,7 +1069,6 @@ class ExplicitReferenceCollector
case TemplateArgument::Pack:
case TemplateArgument::Type:
case TemplateArgument::Expression:
case TemplateArgument::UncommonValue:
break; // Handled by VisitType and VisitExpression.
};
return RecursiveASTVisitor::TraverseTemplateArgumentLoc(A);
Expand Down
3 changes: 1 addition & 2 deletions clang-tools-extra/clangd/index/remote/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,7 @@ class IndexClient : public clangd::SymbolIndex {
});
}

llvm::unique_function<bool(llvm::StringRef) const>
indexedFiles() const override {
llvm::unique_function<bool(llvm::StringRef) const> indexedFiles() const {
// FIXME: For now we always return "false" regardless of whether the file
// was indexed or not. A possible implementation could be based on
// the idea that we do not want to send a request at every
Expand Down
Loading

0 comments on commit 52b1011

Please sign in to comment.