Skip to content

Commit 76e5023

Browse files
committedFeb 20, 2018
[clang-tidy] Replace the usage of std::uncaught_exception with std::uncaught_exceptions
Patch by: Daniel Kolozsvari! Differential Revision: https://reviews.llvm.org/D40787 llvm-svn: 325572
1 parent b8f369d commit 76e5023

File tree

8 files changed

+294
-0
lines changed

8 files changed

+294
-0
lines changed
 

‎clang-tools-extra/clang-tidy/modernize/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ add_clang_library(clangTidyModernizeModule
2727
UseNullptrCheck.cpp
2828
UseOverrideCheck.cpp
2929
UseTransparentFunctorsCheck.cpp
30+
UseUncaughtExceptionsCheck.cpp
3031
UseUsingCheck.cpp
3132

3233
LINK_LIBS

‎clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "UseNullptrCheck.h"
3434
#include "UseOverrideCheck.h"
3535
#include "UseTransparentFunctorsCheck.h"
36+
#include "UseUncaughtExceptionsCheck.h"
3637
#include "UseUsingCheck.h"
3738

3839
using namespace clang::ast_matchers;
@@ -78,6 +79,8 @@ class ModernizeModule : public ClangTidyModule {
7879
CheckFactories.registerCheck<UseOverrideCheck>("modernize-use-override");
7980
CheckFactories.registerCheck<UseTransparentFunctorsCheck>(
8081
"modernize-use-transparent-functors");
82+
CheckFactories.registerCheck<UseUncaughtExceptionsCheck>(
83+
"modernize-use-uncaught-exceptions");
8184
CheckFactories.registerCheck<UseUsingCheck>("modernize-use-using");
8285
}
8386

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//===--- UseUncaughtExceptionsCheck.cpp - clang-tidy--------------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "UseUncaughtExceptionsCheck.h"
11+
#include "clang/AST/ASTContext.h"
12+
#include "clang/ASTMatchers/ASTMatchFinder.h"
13+
14+
using namespace clang::ast_matchers;
15+
16+
namespace clang {
17+
namespace tidy {
18+
namespace modernize {
19+
20+
void UseUncaughtExceptionsCheck::registerMatchers(MatchFinder *Finder) {
21+
if (!getLangOpts().CPlusPlus17)
22+
return;
23+
24+
std::string MatchText = "::std::uncaught_exception";
25+
26+
// Using declaration: warning and fix-it.
27+
Finder->addMatcher(
28+
usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(hasName(MatchText))))
29+
.bind("using_decl"),
30+
this);
31+
32+
// DeclRefExpr: warning, no fix-it.
33+
Finder->addMatcher(declRefExpr(allOf(to(functionDecl(hasName(MatchText))),
34+
unless(callExpr())))
35+
.bind("decl_ref_expr"),
36+
this);
37+
38+
// CallExpr: warning, fix-it.
39+
Finder->addMatcher(
40+
callExpr(allOf(hasDeclaration(functionDecl(hasName(MatchText))),
41+
unless(hasAncestor(initListExpr()))))
42+
.bind("call_expr"),
43+
this);
44+
// CallExpr in initialisation list: warning, fix-it with avoiding narrowing
45+
// conversions.
46+
Finder->addMatcher(
47+
callExpr(allOf(hasAncestor(initListExpr()),
48+
hasDeclaration(functionDecl(hasName(MatchText)))))
49+
.bind("init_call_expr"),
50+
this);
51+
}
52+
53+
void UseUncaughtExceptionsCheck::check(const MatchFinder::MatchResult &Result) {
54+
SourceLocation BeginLoc;
55+
SourceLocation EndLoc;
56+
const CallExpr *C = Result.Nodes.getNodeAs<CallExpr>("init_call_expr");
57+
bool WarnOnly = false;
58+
59+
if (C) {
60+
BeginLoc = C->getLocStart();
61+
EndLoc = C->getLocEnd();
62+
} else if (const auto *E = Result.Nodes.getNodeAs<CallExpr>("call_expr")) {
63+
BeginLoc = E->getLocStart();
64+
EndLoc = E->getLocEnd();
65+
} else if (const auto *D =
66+
Result.Nodes.getNodeAs<DeclRefExpr>("decl_ref_expr")) {
67+
BeginLoc = D->getLocStart();
68+
EndLoc = D->getLocEnd();
69+
WarnOnly = true;
70+
} else {
71+
const auto *U = Result.Nodes.getNodeAs<UsingDecl>("using_decl");
72+
assert(U && "Null pointer, no node provided");
73+
BeginLoc = U->getNameInfo().getBeginLoc();
74+
EndLoc = U->getNameInfo().getEndLoc();
75+
}
76+
77+
auto Diag = diag(BeginLoc, "'std::uncaught_exception' is deprecated, use "
78+
"'std::uncaught_exceptions' instead");
79+
80+
if (!BeginLoc.isMacroID()) {
81+
StringRef Text =
82+
Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
83+
*Result.SourceManager, getLangOpts());
84+
85+
Text.consume_back("()");
86+
int TextLength = Text.size();
87+
88+
if (WarnOnly) {
89+
return;
90+
}
91+
92+
if (!C) {
93+
Diag << FixItHint::CreateInsertion(BeginLoc.getLocWithOffset(TextLength),
94+
"s");
95+
} else {
96+
Diag << FixItHint::CreateReplacement(C->getSourceRange(),
97+
"std::uncaught_exceptions() > 0");
98+
}
99+
}
100+
}
101+
102+
} // namespace modernize
103+
} // namespace tidy
104+
} // namespace clang
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===--- UseUncaughtExceptionsCheck.h - clang-tidy------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_UNCAUGHT_EXCEPTIONS_H
11+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_UNCAUGHT_EXCEPTIONS_H
12+
13+
#include "../ClangTidy.h"
14+
15+
namespace clang {
16+
namespace tidy {
17+
namespace modernize {
18+
19+
/// This check will warn on calls to std::uncaught_exception and replace them with calls to
20+
/// std::uncaught_exceptions, since std::uncaught_exception was deprecated in C++17. In case of
21+
/// macro ID there will be only a warning without fixits.
22+
///
23+
/// For the user-facing documentation see:
24+
/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-uncaught-exceptions.html
25+
class UseUncaughtExceptionsCheck : public ClangTidyCheck {
26+
public:
27+
UseUncaughtExceptionsCheck(StringRef Name, ClangTidyContext *Context)
28+
: ClangTidyCheck(Name, Context) {}
29+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
30+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
31+
};
32+
33+
} // namespace modernize
34+
} // namespace tidy
35+
} // namespace clang
36+
37+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_UNCAUGHT_EXCEPTIONS_H

‎clang-tools-extra/docs/ReleaseNotes.rst

+5
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ Improvements to clang-tidy
105105

106106
Diagnoses when a temporary object that appears to be an exception is constructed but not thrown.
107107

108+
- New `modernize-use-uncaught-exceptions
109+
<http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-uncaught-exceptions.html>`_ check
110+
111+
Finds and replaces deprecated uses of std::uncaught_exception to std::uncaught_exceptions()
112+
108113
Improvements to include-fixer
109114
-----------------------------
110115

‎clang-tools-extra/docs/clang-tidy/checks/list.rst

+1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ Clang-Tidy Checks
177177
modernize-use-nullptr
178178
modernize-use-override
179179
modernize-use-transparent-functors
180+
modernize-use-uncaught-exceptions
180181
modernize-use-using
181182
mpi-buffer-deref
182183
mpi-type-mismatch
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
.. title:: clang-tidy - modernize-use-uncaught-exceptions
2+
3+
modernize-use-uncaught-exceptions
4+
====================================
5+
6+
This check will warn on calls to ``std::uncaught_exception`` and replace them with
7+
calls to ``std::uncaught_exceptions``, since ``std::uncaught_exception`` was deprecated
8+
in C++17.
9+
10+
Below are a few examples of what kind of occurrences will be found and what
11+
they will be replaced with.
12+
13+
.. code-block:: c++
14+
15+
#define MACRO1 std::uncaught_exception
16+
#define MACRO2 std::uncaught_exception
17+
18+
int uncaught_exception() {
19+
return 0;
20+
}
21+
22+
int main() {
23+
int res;
24+
25+
res = uncaught_exception();
26+
// No warning, since it is not the deprecated function from namespace std
27+
28+
res = MACRO2();
29+
// Warning, but will not be replaced
30+
31+
res = std::uncaught_exception();
32+
// Warning and replaced
33+
34+
using std::uncaught_exception;
35+
// Warning and replaced
36+
37+
res = uncaught_exception();
38+
// Warning and replaced
39+
}
40+
41+
After applying the fixes the code will look like the following:
42+
43+
.. code-block:: c++
44+
45+
#define MACRO1 std::uncaught_exception
46+
#define MACRO2 std::uncaught_exception
47+
48+
int uncaught_exception() {
49+
return 0;
50+
}
51+
52+
int main() {
53+
int res;
54+
55+
res = uncaught_exception();
56+
57+
res = MACRO2();
58+
59+
res = std::uncaught_exceptions();
60+
61+
using std::uncaught_exceptions;
62+
63+
res = uncaught_exceptions();
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// RUN: %check_clang_tidy %s modernize-use-uncaught-exceptions %t -- -- -std=c++1z
2+
#define MACRO std::uncaught_exception
3+
// CHECK-FIXES: #define MACRO std::uncaught_exception
4+
5+
bool uncaught_exception() {
6+
return 0;
7+
}
8+
9+
namespace std {
10+
bool uncaught_exception() {
11+
return false;
12+
}
13+
14+
int uncaught_exceptions() {
15+
return 0;
16+
}
17+
}
18+
19+
template <typename T>
20+
bool doSomething(T t) {
21+
return t();
22+
// CHECK-FIXES: return t();
23+
}
24+
25+
template <bool (*T)()>
26+
bool doSomething2() {
27+
return T();
28+
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
29+
// CHECK-FIXES: return T();
30+
}
31+
32+
void no_warn() {
33+
34+
uncaught_exception();
35+
// CHECK-FIXES: uncaught_exception();
36+
37+
doSomething(uncaught_exception);
38+
// CHECK-FIXES: doSomething(uncaught_exception);
39+
}
40+
41+
void warn() {
42+
43+
std::uncaught_exception();
44+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
45+
// CHECK-FIXES: std::uncaught_exceptions();
46+
47+
using std::uncaught_exception;
48+
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
49+
// CHECK-FIXES: using std::uncaught_exceptions;
50+
51+
uncaught_exception();
52+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
53+
// CHECK-FIXES: uncaught_exceptions();
54+
55+
bool b{uncaught_exception()};
56+
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
57+
// CHECK-FIXES: bool b{std::uncaught_exceptions() > 0};
58+
59+
MACRO();
60+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
61+
// CHECK-FIXES: MACRO();
62+
63+
doSomething(std::uncaught_exception);
64+
// CHECK-MESSAGES: [[@LINE-1]]:15: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
65+
// CHECK-FIXES: doSomething(std::uncaught_exception);
66+
67+
doSomething(uncaught_exception);
68+
// CHECK-MESSAGES: [[@LINE-1]]:15: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
69+
// CHECK-FIXES: doSomething(uncaught_exception);
70+
71+
bool (*foo)();
72+
foo = &uncaught_exception;
73+
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
74+
// CHECK-FIXES: foo = &uncaught_exception;
75+
76+
doSomething2<uncaught_exception>();
77+
// CHECK-MESSAGES: [[@LINE-1]]:16: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
78+
// CHECK-FIXES: doSomething2<uncaught_exception>();
79+
}

0 commit comments

Comments
 (0)
Please sign in to comment.