OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "FindBadConstructsConsumer.h" | 5 #include "FindBadConstructsConsumer.h" |
6 | 6 |
7 #include "clang/Frontend/CompilerInstance.h" | 7 #include "clang/Frontend/CompilerInstance.h" |
8 #include "clang/AST/Attr.h" | 8 #include "clang/AST/Attr.h" |
9 #include "clang/Lex/Lexer.h" | 9 #include "clang/Lex/Lexer.h" |
10 #include "llvm/Support/raw_ostream.h" | 10 #include "llvm/Support/raw_ostream.h" |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 if (!record->hasUserDeclaredConstructor()) { | 276 if (!record->hasUserDeclaredConstructor()) { |
277 emitWarning(record_location, | 277 emitWarning(record_location, |
278 "Complex class/struct needs an explicit out-of-line " | 278 "Complex class/struct needs an explicit out-of-line " |
279 "constructor."); | 279 "constructor."); |
280 } else { | 280 } else { |
281 // Iterate across all the constructors in this file and yell if we | 281 // Iterate across all the constructors in this file and yell if we |
282 // find one that tries to be inline. | 282 // find one that tries to be inline. |
283 for (CXXRecordDecl::ctor_iterator it = record->ctor_begin(); | 283 for (CXXRecordDecl::ctor_iterator it = record->ctor_begin(); |
284 it != record->ctor_end(); | 284 it != record->ctor_end(); |
285 ++it) { | 285 ++it) { |
| 286 // The current check is buggy. An implicit copy constructor does not |
| 287 // have an inline body, so this check never fires for classes with a |
| 288 // user-declared out-of-line constructor. |
286 if (it->hasInlineBody()) { | 289 if (it->hasInlineBody()) { |
287 if (it->isCopyConstructor() && | 290 if (it->isCopyConstructor() && |
288 !record->hasUserDeclaredCopyConstructor()) { | 291 !record->hasUserDeclaredCopyConstructor()) { |
289 emitWarning(record_location, | 292 emitWarning(record_location, |
290 "Complex class/struct needs an explicit out-of-line " | 293 "Complex class/struct needs an explicit out-of-line " |
291 "copy constructor."); | 294 "copy constructor."); |
292 } else { | 295 } else { |
293 emitWarning(it->getInnerLocStart(), | 296 emitWarning(it->getInnerLocStart(), |
294 "Complex constructor has an inlined body."); | 297 "Complex constructor has an inlined body."); |
295 } | 298 } |
| 299 } else if (it->isInlined() && (!it->isCopyOrMoveConstructor() || |
| 300 it->isExplicitlyDefaulted())) { |
| 301 // isInlined() is a more reliable check than hasInlineBody(), but |
| 302 // unfortunately, it results in warnings for implicit copy/move |
| 303 // constructors in the previously mentioned situation. To preserve |
| 304 // compatibility with existing Chromium code, only warn if it's an |
| 305 // explicitly defaulted copy or move constructor. |
| 306 emitWarning(it->getInnerLocStart(), |
| 307 "Complex constructor has an inlined body."); |
296 } | 308 } |
297 } | 309 } |
298 } | 310 } |
299 } | 311 } |
300 | 312 |
301 // The destructor side is equivalent except that we don't check for | 313 // The destructor side is equivalent except that we don't check for |
302 // trivial members; 20 ints don't need a destructor. | 314 // trivial members; 20 ints don't need a destructor. |
303 if (dtor_score >= 10 && !record->hasTrivialDestructor()) { | 315 if (dtor_score >= 10 && !record->hasTrivialDestructor()) { |
304 if (!record->hasUserDeclaredDestructor()) { | 316 if (!record->hasUserDeclaredDestructor()) { |
305 emitWarning(record_location, | 317 emitWarning(record_location, |
306 "Complex class/struct needs an explicit out-of-line " | 318 "Complex class/struct needs an explicit out-of-line " |
307 "destructor."); | 319 "destructor."); |
308 } else if (CXXDestructorDecl* dtor = record->getDestructor()) { | 320 } else if (CXXDestructorDecl* dtor = record->getDestructor()) { |
309 if (dtor->hasInlineBody()) { | 321 if (dtor->isInlined()) { |
310 emitWarning(dtor->getInnerLocStart(), | 322 emitWarning(dtor->getInnerLocStart(), |
311 "Complex destructor has an inline body."); | 323 "Complex destructor has an inline body."); |
312 } | 324 } |
313 } | 325 } |
314 } | 326 } |
315 } | 327 } |
316 | 328 |
317 bool FindBadConstructsConsumer::InTestingNamespace(const Decl* record) { | 329 bool FindBadConstructsConsumer::InTestingNamespace(const Decl* record) { |
318 return GetNamespace(record).find("testing") != std::string::npos; | 330 return GetNamespace(record).find("testing") != std::string::npos; |
319 } | 331 } |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 // one of those, it means there is at least one member after a factory. | 785 // one of those, it means there is at least one member after a factory. |
774 if (weak_ptr_factory_location.isValid() && | 786 if (weak_ptr_factory_location.isValid() && |
775 !param_is_weak_ptr_factory_to_self) { | 787 !param_is_weak_ptr_factory_to_self) { |
776 diagnostic().Report(weak_ptr_factory_location, | 788 diagnostic().Report(weak_ptr_factory_location, |
777 diag_weak_ptr_factory_order_); | 789 diag_weak_ptr_factory_order_); |
778 } | 790 } |
779 } | 791 } |
780 } | 792 } |
781 | 793 |
782 } // namespace chrome_checker | 794 } // namespace chrome_checker |
OLD | NEW |