Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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/abseil/AbseilTidyModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "StringFindStrContainsCheck.h"
#include "TimeComparisonCheck.h"
#include "TimeSubtractionCheck.h"
#include "UncheckedStatusOrAccessCheck.h"
#include "UpgradeDurationConversionsCheck.h"

namespace clang::tidy {
Expand Down Expand Up @@ -67,6 +68,8 @@ class AbseilModule : public ClangTidyModule {
CheckFactories.registerCheck<TimeComparisonCheck>("abseil-time-comparison");
CheckFactories.registerCheck<TimeSubtractionCheck>(
"abseil-time-subtraction");
CheckFactories.registerCheck<UncheckedStatusOrAccessCheck>(
"abseil-unchecked-statusor-access");
CheckFactories.registerCheck<UpgradeDurationConversionsCheck>(
"abseil-upgrade-duration-conversions");
}
Expand Down
1 change: 1 addition & 0 deletions clang-tools-extra/clang-tidy/abseil/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ add_clang_library(clangTidyAbseilModule STATIC
TimeComparisonCheck.cpp
TimeSubtractionCheck.cpp
UpgradeDurationConversionsCheck.cpp
UncheckedStatusOrAccessCheck.cpp

LINK_LIBS
clangTidy
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===----------------------------------------------------------------------===//
//
// 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 "UncheckedStatusOrAccessCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
#include "clang/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Error.h"

namespace clang::tidy::abseil {
using ast_matchers::MatchFinder;
using dataflow::statusor_model::UncheckedStatusOrAccessDiagnoser;
using dataflow::statusor_model::UncheckedStatusOrAccessModel;

static constexpr llvm::StringLiteral FuncID("fun");

void UncheckedStatusOrAccessCheck::registerMatchers(MatchFinder *Finder) {
using namespace ast_matchers;

auto HasStatusOrCallDescendant =
hasDescendant(callExpr(callee(cxxMethodDecl(ofClass(hasAnyName(
"absl::StatusOr", "absl::internal_statusor::OperatorBase"))))));
Finder->addMatcher(functionDecl(unless(isExpansionInSystemHeader()),
hasBody(HasStatusOrCallDescendant))
.bind(FuncID),
this);
Finder->addMatcher(
cxxConstructorDecl(hasAnyConstructorInitializer(
withInitializer(HasStatusOrCallDescendant)))
.bind(FuncID),
this);
}

void UncheckedStatusOrAccessCheck::check(
const MatchFinder::MatchResult &Result) {
if (Result.SourceManager->getDiagnostics().hasUncompilableErrorOccurred())
return;

const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>(FuncID);
if (FuncDecl->isTemplated())
return;

UncheckedStatusOrAccessDiagnoser Diagnoser;
if (llvm::Expected<llvm::SmallVector<SourceLocation>> Locs =
dataflow::diagnoseFunction<UncheckedStatusOrAccessModel,
SourceLocation>(*FuncDecl, *Result.Context,
Diagnoser))
for (const SourceLocation &Loc : *Locs)
diag(Loc, "unchecked access to 'absl::StatusOr' value");
else
llvm::consumeError(Locs.takeError());
}

bool UncheckedStatusOrAccessCheck::isLanguageVersionSupported(
const LangOptions &LangOpts) const {
return LangOpts.CPlusPlus;
}

} // namespace clang::tidy::abseil
24 changes: 24 additions & 0 deletions clang-tools-extra/clang-tidy/abseil/UncheckedStatusOrAccessCheck.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_UNCHECKEDSTATUSORACCESSCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_UNCHECKEDSTATUSORACCESSCHECK_H

#include "../ClangTidyCheck.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"

namespace clang::tidy::abseil {

// Warns when the code is unwrapping an absl::StatusOr<T> object without
// assuring that it contains a value.
//
// For details on the dataflow analysis implemented in this check see:
// clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
class UncheckedStatusOrAccessCheck : public ClangTidyCheck {
public:
using ClangTidyCheck::ClangTidyCheck;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override;
};

} // namespace clang::tidy::abseil

#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_UNCHECKEDSTATUSORACCESSCHECK_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 @@ -199,6 +199,11 @@ Improvements to clang-tidy
New checks
^^^^^^^^^^

- New :doc:`abseil-unchecked-statusor-access
<clang-tidy/checks/abseil/unchecked-statusor-access>` check.

Finds uses of ``absl::StatusOr`` without checking if a value is present.

- New :doc:`bugprone-derived-method-shadowing-base-method
<clang-tidy/checks/bugprone/derived-method-shadowing-base-method>` check.

Expand Down
Loading
Loading