namespace tidy {
namespace modernize {
+UseUsingCheck::UseUsingCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ IgnoreMacros(Options.get("IgnoreMacros", true)) {}
+
void UseUsingCheck::registerMatchers(MatchFinder *Finder) {
if (!getLangOpts().CPlusPlus11)
return;
auto &Context = *Result.Context;
auto &SM = *Result.SourceManager;
+ SourceLocation StartLoc = MatchedDecl->getLocStart();
+
+ if (StartLoc.isMacroID() && IgnoreMacros)
+ return;
+
auto Diag =
- diag(MatchedDecl->getLocStart(), "use 'using' instead of 'typedef'");
+ diag(StartLoc, "use 'using' instead of 'typedef'");
- SourceLocation StartLoc = MatchedDecl->getLocStart();
- if (StartLoc.isMacroID())
+ // do not fix if there is macro or array
+ if (MatchedDecl->getUnderlyingType()->isArrayType() || StartLoc.isMacroID())
return;
if (CheckRemoval(SM, StartLoc, Context)) {
+ auto printPolicy = PrintingPolicy(getLangOpts());
+ printPolicy.SuppressScope = true;
+ printPolicy.ConstantArraySizeAsWritten = true;
+ printPolicy.UseVoidForZeroParams = false;
+
Diag << FixItHint::CreateReplacement(
MatchedDecl->getSourceRange(),
"using " + MatchedDecl->getNameAsString() + " = " +
- MatchedDecl->getUnderlyingType().getAsString(getLangOpts()));
+ MatchedDecl->getUnderlyingType().getAsString(printPolicy));
}
}
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-using.html
class UseUsingCheck : public ClangTidyCheck {
+
+ const bool IgnoreMacros;
+
public:
- UseUsingCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {}
+ UseUsingCheck(StringRef Name, ClangTidyContext *Context);
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override {
+ Options.store(Opts, "IgnoreMacros", IgnoreMacros);
+ }
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
--- /dev/null
+// RUN: %check_clang_tidy %s modernize-use-using %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-using.IgnoreMacros, value: 0}]}" \
+// RUN: -- -std=c++11 -I %S/Inputs/modernize-use-using
+
+#define CODE typedef int INT
+
+CODE;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: #define CODE typedef int INT
+// CHECK-FIXES: CODE;
+
+struct Foo;
+#define Bar Baz
+typedef Foo Bar;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: #define Bar Baz
+// CHECK-FIXES: using Baz = Foo;
+
+#define TYPEDEF typedef
+TYPEDEF Foo Bak;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: #define TYPEDEF typedef
+// CHECK-FIXES: TYPEDEF Foo Bak;
#define CODE typedef int INT
CODE;
-// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
// CHECK-FIXES: #define CODE typedef int INT
// CHECK-FIXES: CODE;
#define TYPEDEF typedef
TYPEDEF Foo Bak;
-// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
// CHECK-FIXES: #define TYPEDEF typedef
// CHECK-FIXES: TYPEDEF Foo Bak;
struct { int d; } typedef S4;
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
// CHECK-FIXES: struct { int d; } typedef S4;
+
+namespace my_space {
+ class my_cclass {};
+ typedef my_cclass FuncType;
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using FuncType = my_cclass;
+}
+
+#define lol 4
+typedef unsigned Map[lol];
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+
+typedef void (*fun_type)();
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using fun_type = void (*)();