summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2016-03-22 13:37:44 +0000
committerAaron Ballman <aaron@aaronballman.com>2016-03-22 13:37:44 +0000
commit6fc0622da020de6f5313d718ebbf8f6629225411 (patch)
tree986858bc8f2da39ba957a1e7ac4d7a3abe8a661d
parent345b712b472a42b80175a548bcf8877c5f8f573b (diff)
downloadclang-tools-extra-6fc0622da020de6f5313d718ebbf8f6629225411.tar.gz
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
-rw-r--r--clang-tidy/cppcoreguidelines-pro-type-member-init-delayed.cpp32
-rw-r--r--clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp9
-rw-r--r--clang-tidy/modernize-redundant-void-arg-delayed.cpp28
-rw-r--r--clang-tidy/modernize/RedundantVoidArgCheck.cpp10
4 files changed, 71 insertions, 8 deletions
diff --git a/clang-tidy/cppcoreguidelines-pro-type-member-init-delayed.cpp b/clang-tidy/cppcoreguidelines-pro-type-member-init-delayed.cpp
new file mode 100644
index 00000000..356aa007
--- /dev/null
+++ b/clang-tidy/cppcoreguidelines-pro-type-member-init-delayed.cpp
@@ -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;
+};
diff --git a/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp b/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
index 6e5896a9..672d222e 100644
--- a/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
+++ b/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
@@ -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;
diff --git a/clang-tidy/modernize-redundant-void-arg-delayed.cpp b/clang-tidy/modernize-redundant-void-arg-delayed.cpp
new file mode 100644
index 00000000..dd887758
--- /dev/null
+++ b/clang-tidy/modernize-redundant-void-arg-delayed.cpp
@@ -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;
+ }
+};
diff --git a/clang-tidy/modernize/RedundantVoidArgCheck.cpp b/clang-tidy/modernize/RedundantVoidArgCheck.cpp
index 4c8f681b..eb971a91 100644
--- a/clang-tidy/modernize/RedundantVoidArgCheck.cpp
+++ b/clang-tidy/modernize/RedundantVoidArgCheck.cpp
@@ -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 {