Skip to content

Commit 19f99fe

Browse files
authored
Merge pull request #331
Private/sync to llvm svn 362662
2 parents 7b152a8 + a8ac649 commit 19f99fe

File tree

6,413 files changed

+167963
-42466
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

6,413 files changed

+167963
-42466
lines changed

clang-tools-extra/clang-apply-replacements/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ add_clang_library(clangApplyReplacements
1010
clangBasic
1111
clangRewrite
1212
clangToolingCore
13-
clangToolingRefactor
13+
clangToolingRefactoring
1414
)
1515

1616
include_directories(

clang-tools-extra/clang-apply-replacements/tool/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ target_link_libraries(clang-apply-replacements
1212
clangFormat
1313
clangRewrite
1414
clangToolingCore
15-
clangToolingRefactor
15+
clangToolingRefactoring
1616
)
1717

1818
install(TARGETS clang-apply-replacements

clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ namespace clang {
1616
namespace tidy {
1717
namespace bugprone {
1818

19+
UnhandledSelfAssignmentCheck::UnhandledSelfAssignmentCheck(
20+
StringRef Name, ClangTidyContext *Context)
21+
: ClangTidyCheck(Name, Context),
22+
WarnOnlyIfThisHasSuspiciousField(
23+
Options.get("WarnOnlyIfThisHasSuspiciousField", true)) {}
24+
25+
void UnhandledSelfAssignmentCheck::storeOptions(
26+
ClangTidyOptions::OptionMap &Opts) {
27+
Options.store(Opts, "WarnOnlyIfThisHasSuspiciousField",
28+
WarnOnlyIfThisHasSuspiciousField);
29+
}
30+
1931
void UnhandledSelfAssignmentCheck::registerMatchers(MatchFinder *Finder) {
2032
if (!getLangOpts().CPlusPlus)
2133
return;
@@ -61,29 +73,32 @@ void UnhandledSelfAssignmentCheck::registerMatchers(MatchFinder *Finder) {
6173
cxxMethodDecl(unless(hasDescendant(cxxMemberCallExpr(callee(cxxMethodDecl(
6274
hasName("operator="), ofClass(equalsBoundNode("class"))))))));
6375

64-
// Matcher for standard smart pointers.
65-
const auto SmartPointerType = qualType(hasUnqualifiedDesugaredType(
66-
recordType(hasDeclaration(classTemplateSpecializationDecl(
67-
hasAnyName("::std::shared_ptr", "::std::unique_ptr",
68-
"::std::weak_ptr", "::std::auto_ptr"),
69-
templateArgumentCountIs(1))))));
70-
71-
// We will warn only if the class has a pointer or a C array field which
72-
// probably causes a problem during self-assignment (e.g. first resetting the
73-
// pointer member, then trying to access the object pointed by the pointer, or
74-
// memcpy overlapping arrays).
75-
const auto ThisHasSuspiciousField = cxxMethodDecl(ofClass(cxxRecordDecl(
76-
has(fieldDecl(anyOf(hasType(pointerType()), hasType(SmartPointerType),
77-
hasType(arrayType())))))));
78-
79-
Finder->addMatcher(
80-
cxxMethodDecl(ofClass(cxxRecordDecl().bind("class")),
81-
isCopyAssignmentOperator(), IsUserDefined,
82-
HasReferenceParam, HasNoSelfCheck,
83-
unless(HasNonTemplateSelfCopy), unless(HasTemplateSelfCopy),
84-
HasNoNestedSelfAssign, ThisHasSuspiciousField)
85-
.bind("copyAssignmentOperator"),
86-
this);
76+
DeclarationMatcher AdditionalMatcher = cxxMethodDecl();
77+
if (WarnOnlyIfThisHasSuspiciousField) {
78+
// Matcher for standard smart pointers.
79+
const auto SmartPointerType = qualType(hasUnqualifiedDesugaredType(
80+
recordType(hasDeclaration(classTemplateSpecializationDecl(
81+
hasAnyName("::std::shared_ptr", "::std::unique_ptr",
82+
"::std::weak_ptr", "::std::auto_ptr"),
83+
templateArgumentCountIs(1))))));
84+
85+
// We will warn only if the class has a pointer or a C array field which
86+
// probably causes a problem during self-assignment (e.g. first resetting
87+
// the pointer member, then trying to access the object pointed by the
88+
// pointer, or memcpy overlapping arrays).
89+
AdditionalMatcher = cxxMethodDecl(ofClass(cxxRecordDecl(
90+
has(fieldDecl(anyOf(hasType(pointerType()), hasType(SmartPointerType),
91+
hasType(arrayType())))))));
92+
}
93+
94+
Finder->addMatcher(cxxMethodDecl(ofClass(cxxRecordDecl().bind("class")),
95+
isCopyAssignmentOperator(), IsUserDefined,
96+
HasReferenceParam, HasNoSelfCheck,
97+
unless(HasNonTemplateSelfCopy),
98+
unless(HasTemplateSelfCopy),
99+
HasNoNestedSelfAssign, AdditionalMatcher)
100+
.bind("copyAssignmentOperator"),
101+
this);
87102
}
88103

89104
void UnhandledSelfAssignmentCheck::check(

clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@ namespace bugprone {
2323
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-unhandled-self-assignment.html
2424
class UnhandledSelfAssignmentCheck : public ClangTidyCheck {
2525
public:
26-
UnhandledSelfAssignmentCheck(StringRef Name, ClangTidyContext *Context)
27-
: ClangTidyCheck(Name, Context) {}
26+
UnhandledSelfAssignmentCheck(StringRef Name, ClangTidyContext *Context);
27+
28+
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
2829
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
2930
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
31+
32+
private:
33+
const bool WarnOnlyIfThisHasSuspiciousField;
3034
};
3135

3236
} // namespace bugprone

clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "../ClangTidy.h"
1010
#include "../ClangTidyModule.h"
1111
#include "../ClangTidyModuleRegistry.h"
12+
#include "../bugprone/UnhandledSelfAssignmentCheck.h"
1213
#include "../google/UnnamedNamespaceInHeaderCheck.h"
1314
#include "../misc/NewDeleteOverloadsCheck.h"
1415
#include "../misc/NonCopyableObjects.h"
@@ -49,6 +50,8 @@ class CERTModule : public ClangTidyModule {
4950
// OOP
5051
CheckFactories.registerCheck<performance::MoveConstructorInitCheck>(
5152
"cert-oop11-cpp");
53+
CheckFactories.registerCheck<bugprone::UnhandledSelfAssignmentCheck>(
54+
"cert-oop54-cpp");
5255
// ERR
5356
CheckFactories.registerCheck<misc::ThrowByValueCatchByReferenceCheck>(
5457
"cert-err09-cpp");
@@ -85,6 +88,7 @@ class CERTModule : public ClangTidyModule {
8588
ClangTidyOptions Options;
8689
ClangTidyOptions::OptionMap &Opts = Options.CheckOptions;
8790
Opts["cert-dcl16-c.NewSuffixes"] = "L;LL;LU;LLU";
91+
Opts["cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField"] = "0";
8892
return Options;
8993
}
9094
};

clang-tools-extra/clang-tidy/cert/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ add_clang_library(clangTidyCERTModule
2020
clangBasic
2121
clangLex
2222
clangTidy
23+
clangTidyBugproneModule
2324
clangTidyGoogleModule
2425
clangTidyMiscModule
2526
clangTidyPerformanceModule

clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ void fixInitializerList(const ASTContext &Context, DiagnosticBuilder &Diag,
250250
ProTypeMemberInitCheck::ProTypeMemberInitCheck(StringRef Name,
251251
ClangTidyContext *Context)
252252
: ClangTidyCheck(Name, Context),
253-
IgnoreArrays(Options.get("IgnoreArrays", false)) {}
253+
IgnoreArrays(Options.get("IgnoreArrays", false)),
254+
UseAssignment(Options.getLocalOrGlobal("UseAssignment", false)) {}
254255

255256
void ProTypeMemberInitCheck::registerMatchers(MatchFinder *Finder) {
256257
if (!getLangOpts().CPlusPlus)
@@ -314,6 +315,7 @@ void ProTypeMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
314315

315316
void ProTypeMemberInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
316317
Options.store(Opts, "IgnoreArrays", IgnoreArrays);
318+
Options.store(Opts, "UseAssignment", UseAssignment);
317319
}
318320

319321
// FIXME: Copied from clang/lib/Sema/SemaDeclCXX.cpp.
@@ -338,6 +340,56 @@ static bool isEmpty(ASTContext &Context, const QualType &Type) {
338340
return isIncompleteOrZeroLengthArrayType(Context, Type);
339341
}
340342

343+
static const char *getInitializer(QualType QT, bool UseAssignment) {
344+
const char *DefaultInitializer = "{}";
345+
if (!UseAssignment)
346+
return DefaultInitializer;
347+
348+
if (QT->isPointerType())
349+
return " = nullptr";
350+
351+
const BuiltinType *BT =
352+
dyn_cast<BuiltinType>(QT.getCanonicalType().getTypePtr());
353+
if (!BT)
354+
return DefaultInitializer;
355+
356+
switch (BT->getKind()) {
357+
case BuiltinType::Bool:
358+
return " = false";
359+
case BuiltinType::Float:
360+
return " = 0.0F";
361+
case BuiltinType::Double:
362+
return " = 0.0";
363+
case BuiltinType::LongDouble:
364+
return " = 0.0L";
365+
case BuiltinType::SChar:
366+
case BuiltinType::Char_S:
367+
case BuiltinType::WChar_S:
368+
case BuiltinType::Char16:
369+
case BuiltinType::Char32:
370+
case BuiltinType::Short:
371+
case BuiltinType::Int:
372+
return " = 0";
373+
case BuiltinType::UChar:
374+
case BuiltinType::Char_U:
375+
case BuiltinType::WChar_U:
376+
case BuiltinType::UShort:
377+
case BuiltinType::UInt:
378+
return " = 0U";
379+
case BuiltinType::Long:
380+
return " = 0L";
381+
case BuiltinType::ULong:
382+
return " = 0UL";
383+
case BuiltinType::LongLong:
384+
return " = 0LL";
385+
case BuiltinType::ULongLong:
386+
return " = 0ULL";
387+
388+
default:
389+
return DefaultInitializer;
390+
}
391+
}
392+
341393
void ProTypeMemberInitCheck::checkMissingMemberInitializer(
342394
ASTContext &Context, const CXXRecordDecl &ClassDecl,
343395
const CXXConstructorDecl *Ctor) {
@@ -420,7 +472,7 @@ void ProTypeMemberInitCheck::checkMissingMemberInitializer(
420472
for (const FieldDecl *Field : FieldsToFix) {
421473
Diag << FixItHint::CreateInsertion(
422474
getLocationForEndOfToken(Context, Field->getSourceRange().getEnd()),
423-
"{}");
475+
getInitializer(Field->getType(), UseAssignment));
424476
}
425477
} else if (Ctor) {
426478
// Otherwise, rewrite the constructor's initializer list.

clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ class ProTypeMemberInitCheck : public ClangTidyCheck {
6464

6565
// Whether arrays need to be initialized or not. Default is false.
6666
bool IgnoreArrays;
67+
68+
// Whether fix-its for initialization of fundamental type use assignment
69+
// instead of brace initalization. Only effective in C++11 mode. Default is
70+
// false.
71+
bool UseAssignment;
6772
};
6873

6974
} // namespace cppcoreguidelines
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
//===--- AvoidNSObjectNewCheck.cpp - clang-tidy ---------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "AvoidNSObjectNewCheck.h"
10+
#include "clang/AST/ASTContext.h"
11+
#include "clang/ASTMatchers/ASTMatchFinder.h"
12+
#include "clang/Basic/LangOptions.h"
13+
#include "clang/Basic/SourceLocation.h"
14+
#include "clang/Basic/SourceManager.h"
15+
#include "llvm/Support/FormatVariadic.h"
16+
#include <map>
17+
#include <string>
18+
19+
using namespace clang::ast_matchers;
20+
21+
namespace clang {
22+
namespace tidy {
23+
namespace google {
24+
namespace objc {
25+
26+
static bool isMessageExpressionInsideMacro(const ObjCMessageExpr *Expr) {
27+
SourceLocation ReceiverLocation = Expr->getReceiverRange().getBegin();
28+
if (ReceiverLocation.isMacroID())
29+
return true;
30+
31+
SourceLocation SelectorLocation = Expr->getSelectorStartLoc();
32+
if (SelectorLocation.isMacroID())
33+
return true;
34+
35+
return false;
36+
}
37+
38+
// Walk up the class hierarchy looking for an -init method, returning true
39+
// if one is found and has not been marked unavailable.
40+
static bool isInitMethodAvailable(const ObjCInterfaceDecl *ClassDecl) {
41+
while (ClassDecl != nullptr) {
42+
for (const auto *MethodDecl : ClassDecl->instance_methods()) {
43+
if (MethodDecl->getSelector().getAsString() == "init")
44+
return !MethodDecl->isUnavailable();
45+
}
46+
ClassDecl = ClassDecl->getSuperClass();
47+
}
48+
49+
// No -init method found in the class hierarchy. This should occur only rarely
50+
// in Objective-C code, and only really applies to classes not derived from
51+
// NSObject.
52+
return false;
53+
}
54+
55+
// Returns the string for the Objective-C message receiver. Keeps any generics
56+
// included in the receiver class type, which are stripped if the class type is
57+
// used. While the generics arguments will not make any difference to the
58+
// returned code at this time, the style guide allows them and they should be
59+
// left in any fix-it hint.
60+
static StringRef getReceiverString(SourceRange ReceiverRange,
61+
const SourceManager &SM,
62+
const LangOptions &LangOpts) {
63+
CharSourceRange CharRange = Lexer::makeFileCharRange(
64+
CharSourceRange::getTokenRange(ReceiverRange), SM, LangOpts);
65+
return Lexer::getSourceText(CharRange, SM, LangOpts);
66+
}
67+
68+
static FixItHint getCallFixItHint(const ObjCMessageExpr *Expr,
69+
const SourceManager &SM,
70+
const LangOptions &LangOpts) {
71+
// Check whether the messaged class has a known factory method to use instead
72+
// of -init.
73+
StringRef Receiver =
74+
getReceiverString(Expr->getReceiverRange(), SM, LangOpts);
75+
// Some classes should use standard factory methods instead of alloc/init.
76+
std::map<StringRef, StringRef> ClassToFactoryMethodMap = {{"NSDate", "date"},
77+
{"NSNull", "null"}};
78+
auto FoundClassFactory = ClassToFactoryMethodMap.find(Receiver);
79+
if (FoundClassFactory != ClassToFactoryMethodMap.end()) {
80+
StringRef ClassName = FoundClassFactory->first;
81+
StringRef FactorySelector = FoundClassFactory->second;
82+
std::string NewCall =
83+
llvm::formatv("[{0} {1}]", ClassName, FactorySelector);
84+
return FixItHint::CreateReplacement(Expr->getSourceRange(), NewCall);
85+
}
86+
87+
if (isInitMethodAvailable(Expr->getReceiverInterface())) {
88+
std::string NewCall = llvm::formatv("[[{0} alloc] init]", Receiver);
89+
return FixItHint::CreateReplacement(Expr->getSourceRange(), NewCall);
90+
}
91+
92+
return {}; // No known replacement available.
93+
}
94+
95+
void AvoidNSObjectNewCheck::registerMatchers(MatchFinder *Finder) {
96+
if (!getLangOpts().ObjC)
97+
return;
98+
99+
// Add two matchers, to catch calls to +new and implementations of +new.
100+
Finder->addMatcher(
101+
objcMessageExpr(isClassMessage(), hasSelector("new")).bind("new_call"),
102+
this);
103+
Finder->addMatcher(
104+
objcMethodDecl(isClassMethod(), isDefinition(), hasName("new"))
105+
.bind("new_override"),
106+
this);
107+
}
108+
109+
void AvoidNSObjectNewCheck::check(const MatchFinder::MatchResult &Result) {
110+
if (const auto *CallExpr =
111+
Result.Nodes.getNodeAs<ObjCMessageExpr>("new_call")) {
112+
// Don't warn if the call expression originates from a macro expansion.
113+
if (isMessageExpressionInsideMacro(CallExpr))
114+
return;
115+
116+
diag(CallExpr->getExprLoc(), "do not create objects with +new")
117+
<< getCallFixItHint(CallExpr, *Result.SourceManager,
118+
Result.Context->getLangOpts());
119+
}
120+
121+
if (const auto *DeclExpr =
122+
Result.Nodes.getNodeAs<ObjCMethodDecl>("new_override")) {
123+
diag(DeclExpr->getBeginLoc(), "classes should not override +new");
124+
}
125+
}
126+
127+
} // namespace objc
128+
} // namespace google
129+
} // namespace tidy
130+
} // namespace clang

0 commit comments

Comments
 (0)