Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(249)

Side by Side Diff: tools/clang/plugins/FindBadConstructsConsumer.cpp

Issue 597863002: Update plugin to handle new style rules for virtual annotations. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/clang/plugins/FindBadConstructsConsumer.h ('k') | tools/clang/plugins/Options.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/Lex/Lexer.h" 9 #include "clang/Lex/Lexer.h"
9 #include "llvm/Support/raw_ostream.h" 10 #include "llvm/Support/raw_ostream.h"
10 11
11 using namespace clang; 12 using namespace clang;
12 13
13 namespace chrome_checker { 14 namespace chrome_checker {
14 15
15 namespace { 16 namespace {
16 17
17 const char kMethodRequiresOverride[] = 18 const char kMethodRequiresOverride[] =
18 "[chromium-style] Overriding method must be marked with OVERRIDE."; 19 "[chromium-style] Overriding method must be marked with override or final.";
19 const char kMethodRequiresVirtual[] = 20 const char kRedundantVirtualAnnotation[] =
20 "[chromium-style] Overriding method must have \"virtual\" keyword."; 21 "[chromium-style] %0 is redundant; %1 implies %0.";
22 const char kDtorImplicitVirtual[] =
23 "[chromium-style] destructor is virtual and should be marked as such";
24 const char kVirtualDtorAnnotation[] =
25 "[chromium-style] virtual destructors should not be annotated with %0";
26 // http://llvm.org/bugs/show_bug.cgi?id=21051 has been filed to make this a
27 // Clang warning.
28 const char kBaseMethodVirtualAndFinal[] =
29 "[chromium-style] a virtual method on a base class should not also be "
30 "final; "
Nico 2014/09/24 17:38:06 Once the strict checks are on, we won't need this,
dcheng 2014/09/25 00:12:54 This is, strictly speaking, unnecessary. But I thi
31 "method should be devirtualized";
21 const char kNoExplicitDtor[] = 32 const char kNoExplicitDtor[] =
22 "[chromium-style] Classes that are ref-counted should have explicit " 33 "[chromium-style] Classes that are ref-counted should have explicit "
23 "destructors that are declared protected or private."; 34 "destructors that are declared protected or private.";
24 const char kPublicDtor[] = 35 const char kPublicDtor[] =
25 "[chromium-style] Classes that are ref-counted should have " 36 "[chromium-style] Classes that are ref-counted should have "
26 "destructors that are declared protected or private."; 37 "destructors that are declared protected or private.";
27 const char kProtectedNonVirtualDtor[] = 38 const char kProtectedNonVirtualDtor[] =
28 "[chromium-style] Classes that are ref-counted and have non-private " 39 "[chromium-style] Classes that are ref-counted and have non-private "
29 "destructors should declare their destructor virtual."; 40 "destructors should declare their destructor virtual.";
30 const char kWeakPtrFactoryOrder[] = 41 const char kWeakPtrFactoryOrder[] =
(...skipping 21 matching lines...) Expand all
52 // any namespace qualifiers. This is similar to desugaring, except that for 63 // any namespace qualifiers. This is similar to desugaring, except that for
53 // ElaboratedTypes, desugar will unwrap too much. 64 // ElaboratedTypes, desugar will unwrap too much.
54 const Type* UnwrapType(const Type* type) { 65 const Type* UnwrapType(const Type* type) {
55 if (const ElaboratedType* elaborated = dyn_cast<ElaboratedType>(type)) 66 if (const ElaboratedType* elaborated = dyn_cast<ElaboratedType>(type))
56 return UnwrapType(elaborated->getNamedType().getTypePtr()); 67 return UnwrapType(elaborated->getNamedType().getTypePtr());
57 if (const TypedefType* typedefed = dyn_cast<TypedefType>(type)) 68 if (const TypedefType* typedefed = dyn_cast<TypedefType>(type))
58 return UnwrapType(typedefed->desugar().getTypePtr()); 69 return UnwrapType(typedefed->desugar().getTypePtr());
59 return type; 70 return type;
60 } 71 }
61 72
73 // Unfortunately, there doesn't seem to be a good way to determine the location
74 // of the 'virtual' keyword. It's available in Declarator, but that isn't
75 // accessible from the AST. So instead, make an educated guess that the first
76 // token is probably the virtual keyword. Strictly speaking, this doesn't have
77 // to be true, but it probably will be.
78 // TODO(dcheng): Add a warning to force virtual to always appear first ;-)
79 SourceRange GuessSourceRangeForVirtual(const SourceManager& manager,
80 const CXXMethodDecl* method) {
81 return SourceRange(method->getLocStart(),
82 Lexer::getLocForEndOfToken(
83 method->getLocStart(), 0, manager, LangOptions()));
84 }
85
62 } // namespace 86 } // namespace
63 87
64 FindBadConstructsConsumer::FindBadConstructsConsumer(CompilerInstance& instance, 88 FindBadConstructsConsumer::FindBadConstructsConsumer(CompilerInstance& instance,
65 const Options& options) 89 const Options& options)
66 : ChromeClassTester(instance), options_(options) { 90 : ChromeClassTester(instance), options_(options) {
67 // Register warning/error messages. 91 // Messages for virtual method annotations.
68 diag_method_requires_override_ = 92 diag_method_requires_override_ =
69 diagnostic().getCustomDiagID(getErrorLevel(), kMethodRequiresOverride); 93 diagnostic().getCustomDiagID(getErrorLevel(), kMethodRequiresOverride);
70 diag_method_requires_virtual_ = 94 diag_redundant_virtual_annotation_ = diagnostic().getCustomDiagID(
71 diagnostic().getCustomDiagID(getErrorLevel(), kMethodRequiresVirtual); 95 getErrorLevel(), kRedundantVirtualAnnotation);
96 diag_dtor_implicit_virtual_ = diagnostic().getCustomDiagID(
97 getErrorLevel(), kDtorImplicitVirtual);
98 diag_virtual_dtor_annotation_ =
99 diagnostic().getCustomDiagID(getErrorLevel(), kVirtualDtorAnnotation);
100 diag_base_method_virtual_and_final_ =
101 diagnostic().getCustomDiagID(getErrorLevel(), kBaseMethodVirtualAndFinal);
102
103 // Messages for destructors.
72 diag_no_explicit_dtor_ = 104 diag_no_explicit_dtor_ =
73 diagnostic().getCustomDiagID(getErrorLevel(), kNoExplicitDtor); 105 diagnostic().getCustomDiagID(getErrorLevel(), kNoExplicitDtor);
74 diag_public_dtor_ = 106 diag_public_dtor_ =
75 diagnostic().getCustomDiagID(getErrorLevel(), kPublicDtor); 107 diagnostic().getCustomDiagID(getErrorLevel(), kPublicDtor);
76 diag_protected_non_virtual_dtor_ = 108 diag_protected_non_virtual_dtor_ =
77 diagnostic().getCustomDiagID(getErrorLevel(), kProtectedNonVirtualDtor); 109 diagnostic().getCustomDiagID(getErrorLevel(), kProtectedNonVirtualDtor);
110
111 // Miscellaneous messages.
78 diag_weak_ptr_factory_order_ = 112 diag_weak_ptr_factory_order_ =
79 diagnostic().getCustomDiagID(getErrorLevel(), kWeakPtrFactoryOrder); 113 diagnostic().getCustomDiagID(getErrorLevel(), kWeakPtrFactoryOrder);
80 diag_bad_enum_last_value_ = 114 diag_bad_enum_last_value_ =
81 diagnostic().getCustomDiagID(getErrorLevel(), kBadLastEnumValue); 115 diagnostic().getCustomDiagID(getErrorLevel(), kBadLastEnumValue);
82 116
83 // Registers notes to make it easier to interpret warnings. 117 // Registers notes to make it easier to interpret warnings.
84 diag_note_inheritance_ = 118 diag_note_inheritance_ =
85 diagnostic().getCustomDiagID(DiagnosticsEngine::Note, kNoteInheritance); 119 diagnostic().getCustomDiagID(DiagnosticsEngine::Note, kNoteInheritance);
86 diag_note_implicit_dtor_ = 120 diag_note_implicit_dtor_ =
87 diagnostic().getCustomDiagID(DiagnosticsEngine::Note, kNoteImplicitDtor); 121 diagnostic().getCustomDiagID(DiagnosticsEngine::Note, kNoteImplicitDtor);
88 diag_note_public_dtor_ = 122 diag_note_public_dtor_ =
89 diagnostic().getCustomDiagID(DiagnosticsEngine::Note, kNotePublicDtor); 123 diagnostic().getCustomDiagID(DiagnosticsEngine::Note, kNotePublicDtor);
90 diag_note_protected_non_virtual_dtor_ = diagnostic().getCustomDiagID( 124 diag_note_protected_non_virtual_dtor_ = diagnostic().getCustomDiagID(
91 DiagnosticsEngine::Note, kNoteProtectedNonVirtualDtor); 125 DiagnosticsEngine::Note, kNoteProtectedNonVirtualDtor);
92 } 126 }
93 127
94 void FindBadConstructsConsumer::CheckChromeClass(SourceLocation record_location, 128 void FindBadConstructsConsumer::CheckChromeClass(SourceLocation record_location,
95 CXXRecordDecl* record) { 129 CXXRecordDecl* record) {
96 bool implementation_file = InImplementationFile(record_location); 130 bool implementation_file = InImplementationFile(record_location);
97 131
98 if (!implementation_file) { 132 if (!implementation_file) {
99 // Only check for "heavy" constructors/destructors in header files; 133 // Only check for "heavy" constructors/destructors in header files;
100 // within implementation files, there is no performance cost. 134 // within implementation files, there is no performance cost.
101 CheckCtorDtorWeight(record_location, record); 135 CheckCtorDtorWeight(record_location, record);
102 } 136 }
103 137
104 bool warn_on_inline_bodies = !implementation_file; 138 bool warn_on_inline_bodies = !implementation_file;
105 139
106 // Check that all virtual methods are marked accordingly with both 140 // Check that all virtual methods are annotated with override or final.
107 // virtual and OVERRIDE.
108 CheckVirtualMethods(record_location, record, warn_on_inline_bodies); 141 CheckVirtualMethods(record_location, record, warn_on_inline_bodies);
109 142
110 CheckRefCountedDtors(record_location, record); 143 CheckRefCountedDtors(record_location, record);
111 144
112 if (options_.check_weak_ptr_factory_order) 145 if (options_.check_weak_ptr_factory_order)
113 CheckWeakPtrFactoryMembers(record_location, record); 146 CheckWeakPtrFactoryMembers(record_location, record);
114 } 147 }
115 148
116 void FindBadConstructsConsumer::CheckChromeEnum(SourceLocation enum_location, 149 void FindBadConstructsConsumer::CheckChromeEnum(SourceLocation enum_location,
117 EnumDecl* enum_decl) { 150 EnumDecl* enum_decl) {
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 "destructor."); 276 "destructor.");
244 } else if (CXXDestructorDecl* dtor = record->getDestructor()) { 277 } else if (CXXDestructorDecl* dtor = record->getDestructor()) {
245 if (dtor->hasInlineBody()) { 278 if (dtor->hasInlineBody()) {
246 emitWarning(dtor->getInnerLocStart(), 279 emitWarning(dtor->getInnerLocStart(),
247 "Complex destructor has an inline body."); 280 "Complex destructor has an inline body.");
248 } 281 }
249 } 282 }
250 } 283 }
251 } 284 }
252 285
253 void FindBadConstructsConsumer::CheckVirtualMethod(const CXXMethodDecl* method,
254 bool warn_on_inline_bodies) {
255 if (!method->isVirtual())
256 return;
257
258 if (!method->isVirtualAsWritten()) {
259 SourceLocation loc = method->getTypeSpecStartLoc();
260 if (isa<CXXDestructorDecl>(method))
261 loc = method->getInnerLocStart();
262 SourceManager& manager = instance().getSourceManager();
263 FullSourceLoc full_loc(loc, manager);
264 SourceLocation spelling_loc = manager.getSpellingLoc(loc);
265 diagnostic().Report(full_loc, diag_method_requires_virtual_)
266 << FixItHint::CreateInsertion(spelling_loc, "virtual ");
267 }
268
269 // Virtual methods should not have inline definitions beyond "{}". This
270 // only matters for header files.
271 if (warn_on_inline_bodies && method->hasBody() && method->hasInlineBody()) {
272 if (CompoundStmt* cs = dyn_cast<CompoundStmt>(method->getBody())) {
273 if (cs->size()) {
274 emitWarning(cs->getLBracLoc(),
275 "virtual methods with non-empty bodies shouldn't be "
276 "declared inline.");
277 }
278 }
279 }
280 }
281
282 bool FindBadConstructsConsumer::InTestingNamespace(const Decl* record) { 286 bool FindBadConstructsConsumer::InTestingNamespace(const Decl* record) {
283 return GetNamespace(record).find("testing") != std::string::npos; 287 return GetNamespace(record).find("testing") != std::string::npos;
284 } 288 }
285 289
286 bool FindBadConstructsConsumer::IsMethodInBannedOrTestingNamespace( 290 bool FindBadConstructsConsumer::IsMethodInBannedOrTestingNamespace(
287 const CXXMethodDecl* method) { 291 const CXXMethodDecl* method) {
288 if (InBannedNamespace(method)) 292 if (InBannedNamespace(method))
289 return true; 293 return true;
290 for (CXXMethodDecl::method_iterator i = method->begin_overridden_methods(); 294 for (CXXMethodDecl::method_iterator i = method->begin_overridden_methods();
291 i != method->end_overridden_methods(); 295 i != method->end_overridden_methods();
292 ++i) { 296 ++i) {
293 const CXXMethodDecl* overridden = *i; 297 const CXXMethodDecl* overridden = *i;
294 if (IsMethodInBannedOrTestingNamespace(overridden) || 298 if (IsMethodInBannedOrTestingNamespace(overridden) ||
295 InTestingNamespace(overridden)) { 299 InTestingNamespace(overridden)) {
296 return true; 300 return true;
297 } 301 }
298 } 302 }
299 303
300 return false; 304 return false;
301 } 305 }
302 306
303 void FindBadConstructsConsumer::CheckOverriddenMethod( 307 // Checks that virtual methods are correctly annotated, and have no body in a
304 const CXXMethodDecl* method) { 308 // header file.
305 if (!method->size_overridden_methods() || method->getAttr<OverrideAttr>())
306 return;
307
308 if (isa<CXXDestructorDecl>(method) || method->isPure())
309 return;
310
311 if (IsMethodInBannedOrTestingNamespace(method))
312 return;
313
314 SourceManager& manager = instance().getSourceManager();
315 SourceRange type_info_range =
316 method->getTypeSourceInfo()->getTypeLoc().getSourceRange();
317 FullSourceLoc loc(type_info_range.getBegin(), manager);
318
319 // Build the FixIt insertion point after the end of the method definition,
320 // including any const-qualifiers and attributes, and before the opening
321 // of the l-curly-brace (if inline) or the semi-color (if a declaration).
322 SourceLocation spelling_end =
323 manager.getSpellingLoc(type_info_range.getEnd());
324 if (spelling_end.isValid()) {
325 SourceLocation token_end =
326 Lexer::getLocForEndOfToken(spelling_end, 0, manager, LangOptions());
327 diagnostic().Report(token_end, diag_method_requires_override_)
328 << FixItHint::CreateInsertion(token_end, " OVERRIDE");
329 } else {
330 diagnostic().Report(loc, diag_method_requires_override_);
331 }
332 }
333
334 // Makes sure there is a "virtual" keyword on virtual methods.
335 //
336 // Gmock objects trigger these for each MOCK_BLAH() macro used. So we have a
337 // trick to get around that. If a class has member variables whose types are
338 // in the "testing" namespace (which is how gmock works behind the scenes),
339 // there's a really high chance we won't care about these errors
340 void FindBadConstructsConsumer::CheckVirtualMethods( 309 void FindBadConstructsConsumer::CheckVirtualMethods(
341 SourceLocation record_location, 310 SourceLocation record_location,
342 CXXRecordDecl* record, 311 CXXRecordDecl* record,
343 bool warn_on_inline_bodies) { 312 bool warn_on_inline_bodies) {
313 // Gmock objects trigger these for each MOCK_BLAH() macro used. So we have a
314 // trick to get around that. If a class has member variables whose types are
315 // in the "testing" namespace (which is how gmock works behind the scenes),
316 // there's a really high chance we won't care about these errors
344 for (CXXRecordDecl::field_iterator it = record->field_begin(); 317 for (CXXRecordDecl::field_iterator it = record->field_begin();
345 it != record->field_end(); 318 it != record->field_end();
346 ++it) { 319 ++it) {
347 CXXRecordDecl* record_type = it->getTypeSourceInfo() 320 CXXRecordDecl* record_type = it->getTypeSourceInfo()
348 ->getTypeLoc() 321 ->getTypeLoc()
349 .getTypePtr() 322 .getTypePtr()
350 ->getAsCXXRecordDecl(); 323 ->getAsCXXRecordDecl();
351 if (record_type) { 324 if (record_type) {
352 if (InTestingNamespace(record_type)) { 325 if (InTestingNamespace(record_type)) {
353 return; 326 return;
354 } 327 }
355 } 328 }
356 } 329 }
357 330
358 for (CXXRecordDecl::method_iterator it = record->method_begin(); 331 for (CXXRecordDecl::method_iterator it = record->method_begin();
359 it != record->method_end(); 332 it != record->method_end();
360 ++it) { 333 ++it) {
361 if (it->isCopyAssignmentOperator() || isa<CXXConstructorDecl>(*it)) { 334 if (it->isCopyAssignmentOperator() || isa<CXXConstructorDecl>(*it)) {
362 // Ignore constructors and assignment operators. 335 // Ignore constructors and assignment operators.
363 } else if (isa<CXXDestructorDecl>(*it) && 336 } else if (isa<CXXDestructorDecl>(*it) &&
364 !record->hasUserDeclaredDestructor()) { 337 !record->hasUserDeclaredDestructor()) {
365 // Ignore non-user-declared destructors. 338 // Ignore non-user-declared destructors.
339 } else if (!it->isVirtual()) {
340 continue;
366 } else { 341 } else {
367 CheckVirtualMethod(*it, warn_on_inline_bodies); 342 CheckVirtualAnnotations(*it);
368 CheckOverriddenMethod(*it); 343 if (warn_on_inline_bodies)
344 CheckVirtualBodies(*it);
369 } 345 }
370 } 346 }
371 } 347 }
348
349 // Makes sure that virtual methods are correctly annotated. If a virtual method
350 // overrides a method from a base class, the method must be annotated with
351 // the override keyword. Furthermore, if the method is not meant to be further
352 // subclasses, it must only be annotated with the final keyword.
353 void FindBadConstructsConsumer::CheckVirtualAnnotations(
354 const CXXMethodDecl* method) {
355 bool is_override = method->size_overridden_methods() > 0;
356 bool has_virtual = method->isVirtualAsWritten();
357 OverrideAttr* override_attr = method->getAttr<OverrideAttr>();
358 FinalAttr* final_attr = method->getAttr<FinalAttr>();
359
360 if (method->isPure())
361 return;
362
363 if (IsMethodInBannedOrTestingNamespace(method))
364 return;
365
366 SourceManager& manager = instance().getSourceManager();
367
368 // Destructors should never be annotated override or final.
369 if (isa<CXXDestructorDecl>(method)) {
370 if (!has_virtual && is_override) {
371 diagnostic().Report(method->getLocStart(),
372 diag_dtor_implicit_virtual_)
373 << FixItHint::CreateInsertion(method->getLocStart(), "virtual ");
374 }
375
376 if (!options_.strict_virtual_annotations)
377 return;
378
379 if (override_attr) {
380 diagnostic().Report(override_attr->getLocation(),
381 diag_virtual_dtor_annotation_)
382 << override_attr
383 << FixItHint::CreateRemoval(override_attr->getRange());
384 }
385 if (final_attr) {
386 diagnostic().Report(final_attr->getLocation(),
387 diag_virtual_dtor_annotation_)
388 << final_attr << FixItHint::CreateRemoval(final_attr->getRange());
389 }
390 return;
391 }
392
393 // Complain if a method is annotated virtual && (override || final).
394 if (has_virtual && (override_attr || final_attr) &&
395 options_.strict_virtual_annotations) {
396 diagnostic().Report(method->getLocStart(),
397 diag_redundant_virtual_annotation_)
398 << "virtual"
399 << (override_attr ? static_cast<Attr*>(override_attr) : final_attr)
400 << FixItHint::CreateRemoval(
401 GuessSourceRangeForVirtual(manager, method));
402 }
403
404 // Complain if a method is an override and is not annotated with override or
405 // final.
406 if (is_override && !override_attr && !final_attr) {
407 SourceRange type_info_range =
408 method->getTypeSourceInfo()->getTypeLoc().getSourceRange();
409 FullSourceLoc loc(type_info_range.getBegin(), manager);
410
411 // Build the FixIt insertion point after the end of the method definition,
412 // including any const-qualifiers and attributes, and before the opening
413 // of the l-curly-brace (if inline) or the semi-color (if a declaration).
414 SourceLocation spelling_end =
415 manager.getSpellingLoc(type_info_range.getEnd());
416 if (spelling_end.isValid()) {
417 SourceLocation token_end =
418 Lexer::getLocForEndOfToken(spelling_end, 0, manager, LangOptions());
419 diagnostic().Report(token_end, diag_method_requires_override_)
420 << FixItHint::CreateInsertion(token_end, " override");
421 } else {
422 diagnostic().Report(loc, diag_method_requires_override_);
423 }
424 }
425
426 if (final_attr && override_attr && options_.strict_virtual_annotations) {
427 diagnostic().Report(override_attr->getLocation(),
428 diag_redundant_virtual_annotation_)
429 << override_attr << final_attr
430 << FixItHint::CreateRemoval(override_attr->getRange());
431 }
432
433 if (final_attr && !is_override && options_.strict_virtual_annotations) {
434 diagnostic().Report(method->getLocStart(),
435 diag_base_method_virtual_and_final_)
436 << FixItHint::CreateRemoval(GuessSourceRangeForVirtual(manager, method))
437 << FixItHint::CreateRemoval(final_attr->getRange());
438 }
439 }
440
441 void FindBadConstructsConsumer::CheckVirtualBodies(
442 const CXXMethodDecl* method) {
443 // Virtual methods should not have inline definitions beyond "{}". This
444 // only matters for header files.
445 if (method->hasBody() && method->hasInlineBody()) {
446 if (CompoundStmt* cs = dyn_cast<CompoundStmt>(method->getBody())) {
447 if (cs->size()) {
448 emitWarning(cs->getLBracLoc(),
449 "virtual methods with non-empty bodies shouldn't be "
450 "declared inline.");
451 }
452 }
453 }
454 }
372 455
373 void FindBadConstructsConsumer::CountType(const Type* type, 456 void FindBadConstructsConsumer::CountType(const Type* type,
374 int* trivial_member, 457 int* trivial_member,
375 int* non_trivial_member, 458 int* non_trivial_member,
376 int* templated_non_trivial_member) { 459 int* templated_non_trivial_member) {
377 switch (type->getTypeClass()) { 460 switch (type->getTypeClass()) {
378 case Type::Record: { 461 case Type::Record: {
379 // Simplifying; the whole class isn't trivial if the dtor is, but 462 // Simplifying; the whole class isn't trivial if the dtor is, but
380 // we use this as a signal about complexity. 463 // we use this as a signal about complexity.
381 if (TypeHasNonTrivialDtor(type)) 464 if (TypeHasNonTrivialDtor(type))
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 record->getTypeForDecl()->getAsCXXRecordDecl()) { 759 record->getTypeForDecl()->getAsCXXRecordDecl()) {
677 weak_ptr_factory_location = iter->getLocation(); 760 weak_ptr_factory_location = iter->getLocation();
678 } 761 }
679 } 762 }
680 } 763 }
681 } 764 }
682 } 765 }
683 } 766 }
684 767
685 } // namespace chrome_checker 768 } // namespace chrome_checker
OLDNEW
« no previous file with comments | « tools/clang/plugins/FindBadConstructsConsumer.h ('k') | tools/clang/plugins/Options.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698