Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang-tools-extra/clang-tidy/bsl/BslTidyModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "ClassMemberRedefinedCheck.h"
#include "ClassVirtualBaseCheck.h"
#include "DeclForbiddenCheck.h"
#include "DependentBaseNameCheck.h"
#include "DestructorAccessSpecifierCheck.h"
#include "EnumExplicitCheck.h"
#include "EnumInitCheck.h"
Expand Down Expand Up @@ -71,6 +72,8 @@ class BslModule : public ClangTidyModule {
"bsl-class-virtual-base");
CheckFactories.registerCheck<DeclForbiddenCheck>(
"bsl-decl-forbidden");
CheckFactories.registerCheck<DependentBaseNameCheck>(
"bsl-dependent-base-name");
CheckFactories.registerCheck<DestructorAccessSpecifierCheck>(
"bsl-destructor-access-specifier");
CheckFactories.registerCheck<EnumExplicitCheck>(
Expand Down
1 change: 1 addition & 0 deletions clang-tools-extra/clang-tidy/bsl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ add_clang_library(clangTidyBslModule
ClassMemberRedefinedCheck.cpp
ClassVirtualBaseCheck.cpp
DeclForbiddenCheck.cpp
DependentBaseNameCheck.cpp
DestructorAccessSpecifierCheck.cpp
EnumExplicitCheck.cpp
EnumInitCheck.cpp
Expand Down
76 changes: 76 additions & 0 deletions clang-tools-extra/clang-tidy/bsl/DependentBaseNameCheck.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//===--- DependentBaseNameCheck.cpp - clang-tidy --------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "DependentBaseNameCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace bsl {

AST_MATCHER(CXXRecordDecl, hasAnyDependentBases) {
return Node.hasAnyDependentBases();
}

AST_MATCHER(VarDecl, dependentNameType) {
return isa<DependentNameType>(Node.getType());
}

void DependentBaseNameCheck::registerMatchers(MatchFinder *Finder) {
// Finder->addMatcher(cxxThisExpr().bind("this"), this);
Finder->addMatcher(
varDecl(unless(anyOf(dependentNameType(), hasType(elaboratedType()))),
hasAncestor(cxxRecordDecl(hasAnyDependentBases())))
.bind("var"),
this);

Finder->addMatcher(
declRefExpr(hasAncestor(cxxRecordDecl(hasAnyDependentBases())))
.bind("this"),
this);
// memberexpr
}

void DependentBaseNameCheck::check(const MatchFinder::MatchResult &Result) {
const auto *MatchedDecl = Result.Nodes.getNodeAs<VarDecl>("var");
if (MatchedDecl) {
// if (isa<ElaboratedType>(MatchedDecl->getType())) {
diag(MatchedDecl->getLocation(),
"in a class template with a dependent base, any name that may be "
"found in that dependent base shall be referred to using a "
"qualified-id or this->.");
}

// getBaseTypeIdentifier

// ok
const auto *MatchedExpr = Result.Nodes.getNodeAs<DeclRefExpr>("this");
if (MatchedExpr) {
if (!MatchedExpr->hasQualifier()) {
diag(MatchedExpr->getLocation(),
"in a class template with a dependent base, any name that may be "
"found in that dependent base shall be referred to using a "
"qualified-id or this->.");
}
}

// const auto *MatchedExpr = Result.Nodes.getNodeAs<CXXThisExpr>("this");
// if (MatchedExpr) {
// diag(MatchedExpr->getLocation(), "this");
// if (!MatchedExpr->isImplicit()) {
// diag(MatchedExpr->getLocation(), "not implicit");
// }
// }
}

} // namespace bsl
} // namespace tidy
} // namespace clang
35 changes: 35 additions & 0 deletions clang-tools-extra/clang-tidy/bsl/DependentBaseNameCheck.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===--- DependentBaseNameCheck.h - clang-tidy ------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BSL_DEPENDENTBASENAMECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BSL_DEPENDENTBASENAMECHECK_H

#include "../ClangTidyCheck.h"

namespace clang {
namespace tidy {
namespace bsl {

/// Checks that names in a class template found in its dependent base are
/// referred to using a qualified-id or this->.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bsl-dependent-base-name.html
class DependentBaseNameCheck : public ClangTidyCheck {
public:
DependentBaseNameCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add isLanguageVersionSupported override


} // namespace bsl
} // namespace tidy
} // namespace clang

#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BSL_DEPENDENTBASENAMECHECK_H
5 changes: 5 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ New checks

Warns if unions or bitfields are declared.

- New :doc:`bsl-dependent-base-name
<clang-tidy/checks/bsl-dependent-base-name>` check.

FIXME: add release notes.

- New :doc:`bsl-destructor-access-specifier
<clang-tidy/checks/bsl-destructor-access-specifier>` check.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. title:: clang-tidy - bsl-dependent-base-name

bsl-dependent-base-name
=======================

FIXME: Describe what patterns does the check detect and why. Give examples.
7 changes: 4 additions & 3 deletions clang-tools-extra/docs/clang-tidy/checks/list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,15 @@ Clang-Tidy Checks
`bsl-class-member-redefined <bsl-class-member-redefined.html>`_,
`bsl-class-virtual-base <bsl-class-virtual-base.html>`_,
`bsl-decl-forbidden <bsl-decl-forbidden.html>`_,
`bsl-destructor-access-specifier <bsl-destructor-access-specifier.html>`_, "Yes"
`bsl-dependent-base-name <bsl-dependent-base-name.html>`_, "Yes"
`bsl-destructor-access-specifier <bsl-destructor-access-specifier.html>`_,
`bsl-enum-explicit <bsl-enum-explicit.html>`_,
`bsl-enum-init <bsl-enum-init.html>`_,
`bsl-enum-scoped <bsl-enum-scoped.html>`_,
`bsl-for-loop-counter <bsl-for-loop-counter.html>`_,
`bsl-friend-decl <bsl-friend-decl.html>`_,
`bsl-function-name-use <bsl-function-name-use.html>`_, "Yes"
`bsl-identifier-typographically-unambiguous <bsl-identifier-typographically-unambiguous.html>`_, "Yes"
`bsl-identifier-typographically-unambiguous <bsl-identifier-typographically-unambiguous.html>`_,
`bsl-lambda-implicit-capture <bsl-lambda-implicit-capture.html>`_,
`bsl-lambda-param-list <bsl-lambda-param-list.html>`_,
`bsl-literals-ascii-only <bsl-literals-ascii-only.html>`_,
Expand All @@ -67,7 +68,7 @@ Clang-Tidy Checks
`bsl-literals-uppercase-suffix <bsl-literals-uppercase-suffix.html>`_,
`bsl-literals-user-defined <bsl-literals-user-defined.html>`_,
`bsl-namespace-global <bsl-namespace-global.html>`_,
`bsl-non-pod-classdef <bsl-non-pod-classdef.html>`_, "Yes"
`bsl-non-pod-classdef <bsl-non-pod-classdef.html>`_,
`bsl-non-pod-static <bsl-non-pod-static.html>`_,
`bsl-op-bitwise-operands <bsl-op-bitwise-operands.html>`_, "Yes"
`bsl-op-conditional-subexpr <bsl-op-conditional-subexpr.html>`_,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// RUN: %check_clang_tidy %s bsl-dependent-base-name %t

#include <cstdint>

// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: function 'f' is insufficiently awesome [bsl-dependent-base-name]
typedef int32_t TYPE;
void g ( );

template <typename T>
class B;

int var;

template <typename T>
class A : public B<T>
{
void f1 ( )
{
TYPE t = 0; // Non-compliant Example 1
g ( ); // Non-compliant Example 2
var = 0; // Non-compliant?? use ::var = 0?
Comment thread
ytuo marked this conversation as resolved.
}

void f2 ( )
{
::TYPE t1 = 0; // Compliant - explicit use global TYPE
::g ( ); // Compliant - explicit use global func
typename B<T>::TYPE t2 = 0; // Compliant - explicit use base TYPE
this->g ( ); // Compliant - explicit use base "g"
}
};

// All compliant
template <typename T>
class B
{
public:
typedef T TYPE;
void g ( );
};

template class A<int32_t>;


class C {};

template <typename T>
class D : public C
{
void f1 ( )
{
TYPE t = 0;
g ( );
}
void f2 ( )
{
::TYPE t1 = 0;
::g ( );
typename B<T>::TYPE t2 = 0;
this->g ( );
}
};

class E : C
{
void f1 ( )
{
TYPE t = 0;
g ( );
// A a = a();
// a->f1();
}
void f2 ( )
{
::TYPE t1 = 0;
::g ( );
// typename B<T>::TYPE t2 = 0; // error
// this->g ( ); // error (???)
}
};