Fix crashes from delayed template parsing code that assumed getBody() would return non-null.
Patch by Etienne Bergeron. git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@264049 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
345b712b47
Коммит
6fc0622da0
|
@ -0,0 +1,32 @@
|
|||
// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -fdelayed-template-parsing
|
||||
|
||||
template<class T>
|
||||
struct PositiveFieldBeforeConstructor {
|
||||
PositiveFieldBeforeConstructor() {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F, G, H
|
||||
int F;
|
||||
bool G /* with comment */;
|
||||
int *H;
|
||||
};
|
||||
// Explicit instantiation.
|
||||
template class PositiveFieldBeforeConstructor<int>;
|
||||
|
||||
template<class T>
|
||||
struct PositiveFieldAfterConstructor {
|
||||
PositiveFieldAfterConstructor() {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these built-in/pointer fields: F, G, H
|
||||
int F;
|
||||
bool G /* with comment */;
|
||||
int *H;
|
||||
};
|
||||
// Explicit instantiation.
|
||||
template class PositiveFieldAfterConstructor<int>;
|
||||
|
||||
// This declaration isn't used and won't be parsed 'delayed-template-parsing'.
|
||||
// The body of the declaration is 'null' and may cause crash if not handled
|
||||
// properly by checkers.
|
||||
template<class T>
|
||||
struct UnusedDelayedConstructor {
|
||||
UnusedDelayedConstructor() {}
|
||||
int F;
|
||||
};
|
|
@ -179,6 +179,11 @@ void ProTypeMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
|
|||
const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
|
||||
const auto &MemberFields = Ctor->getParent()->fields();
|
||||
|
||||
// Skip declarations delayed by late template parsing without a body.
|
||||
const Stmt *Body = Ctor->getBody();
|
||||
if (!Body)
|
||||
return;
|
||||
|
||||
SmallPtrSet<const FieldDecl *, 16> FieldsToInit;
|
||||
fieldsRequiringInit(MemberFields, FieldsToInit);
|
||||
if (FieldsToInit.empty())
|
||||
|
@ -193,8 +198,8 @@ void ProTypeMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
|
|||
continue;
|
||||
FieldsToInit.erase(Init->getMember());
|
||||
}
|
||||
removeFieldsInitializedInBody(*Ctor->getBody(), *Result.Context,
|
||||
FieldsToInit);
|
||||
removeFieldsInitializedInBody(*Body, *Result.Context, FieldsToInit);
|
||||
|
||||
if (FieldsToInit.empty())
|
||||
return;
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// RUN: %check_clang_tidy %s modernize-redundant-void-arg %t -- -- -fdelayed-template-parsing
|
||||
|
||||
int foo(void) {
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: redundant void argument list in function definition [modernize-redundant-void-arg]
|
||||
// CHECK-FIXES: {{^}}int foo() {{{$}}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct MyFoo {
|
||||
int foo(void) {
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant void argument list in function definition [modernize-redundant-void-arg]
|
||||
// CHECK-FIXES: {{^}} int foo() {{{$}}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
// Explicit instantiation.
|
||||
template class MyFoo<int>;
|
||||
|
||||
template <class T>
|
||||
struct MyBar {
|
||||
// This declaration isn't instantiated and won't be parsed 'delayed-template-parsing'.
|
||||
int foo(void) {
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant void argument list in function definition [modernize-redundant-void-arg]
|
||||
// CHECK-FIXES: {{^}} int foo() {{{$}}
|
||||
return 0;
|
||||
}
|
||||
};
|
|
@ -102,13 +102,11 @@ void RedundantVoidArgCheck::check(const MatchFinder::MatchResult &Result) {
|
|||
|
||||
void RedundantVoidArgCheck::processFunctionDecl(
|
||||
const MatchFinder::MatchResult &Result, const FunctionDecl *Function) {
|
||||
SourceLocation Start = Function->getLocStart();
|
||||
if (Function->isThisDeclarationADefinition()) {
|
||||
SourceLocation End;
|
||||
if (Function->hasBody())
|
||||
End = Function->getBody()->getLocStart().getLocWithOffset(-1);
|
||||
else
|
||||
End = Function->getLocEnd();
|
||||
const Stmt *Body = Function->getBody();
|
||||
SourceLocation Start = Function->getLocStart();
|
||||
SourceLocation End = Body ? Body->getLocStart().getLocWithOffset(-1) :
|
||||
Function->getLocEnd();
|
||||
removeVoidArgumentTokens(Result, SourceRange(Start, End),
|
||||
"function definition");
|
||||
} else {
|
||||
|
|
Загрузка…
Ссылка в новой задаче