Repository: llvm/llvm-project
File: clang/lib/StaticAnalyzer/Core/BugSuppression.cpp (C++)

Code before:
          dyn_cast_or_null<Decl>(DeclWithIssue->getLexicalDeclContext());
      if (Parent == nullptr || isa<TranslationUnitDecl>(Parent))
        break;

      DeclWithIssue = Parent;
    }
  }

  // While some warnings are attached to AST nodes (mostly path-sensitive
  // checks), others are simply associated with a plain source location
  // or range.  Figuring out the node based on locations can be tricky,
  // so instead, we traverse the whole body of the declaration and gather
  // information on ALL suppressions.  After that we can simply check if
  // any of those suppressions affect the warning in question.
  //
  // Traversing AST of a function is not a heavy operation, but for
  // large functions with a lot of bugs it can make a dent in performance.
  // In order to avoid this scenario, we cache traversal results.
  auto InsertionResult = CachedSuppressionLocations.insert(
      std::make_pair(DeclWithIssue, CachedRanges{}));
  Ranges &SuppressionRanges = InsertionResult.first->second;
  if (InsertionResult.second) {
    llvm::TimeTraceScope TimeScope(
        timeScopeName(DeclWithIssue),
        [DeclWithIssue]() { return getDeclTimeTraceMetadata(DeclWithIssue); });
    // We haven't checked this declaration for suppressions yet!
    CacheInitializer::initialize(DeclWithIssue, SuppressionRanges);
  }

  SourceRange BugRange = Location.asRange();
  const SourceManager &SM = Location.getManager();

  return llvm::any_of(SuppressionRanges,
                      [BugRange, &SM](SourceRange Suppression) {
                        return fullyContains(Suppression, BugRange, SM);
                      });
}


Review comment (bug):
You do a `nullptr` check for the other `dyn_cast` but not this one, is it 💯 that this could not a `nullptr`?

Code after:
preferTemplateDefinitionForTemplateSpecializations(const Decl *D) {
  const auto *SpecializationDecl = dyn_cast<ClassTemplateSpecializationDecl>(D);
  if (!SpecializationDecl)
    return D;

  auto InstantiatedFrom = SpecializationDecl->getInstantiatedFrom();
  if (!InstantiatedFrom)
    return D;

  // This might be a class template.
  if (const auto *Tmpl = InstantiatedFrom.dyn_cast<ClassTemplateDecl *>()) {
    // Interestingly, the source template might be a forward declaration, so we
    // need to find the definition redeclaration.
    for (const auto *Redecl : Tmpl->redecls()) {
      if (cast<ClassTemplateDecl>(Redecl)->isThisDeclarationADefinition()) {
        return Redecl;
      }
    }
    assert(false &&
           "This class template must have a redecl that is a definition");
    return D;
  }

  // It might be a partial specialization.
  const auto *PartialSpecialization =
      InstantiatedFrom.dyn_cast<ClassTemplatePartialSpecializationDecl *>();

  // The partial specialization should be a definition.
  assert(PartialSpecialization->isThisDeclarationADefinition());
  return PartialSpecialization;
}

bool BugSuppression::isSuppressed(const PathDiagnosticLocation &Location,
                                  const Decl *DeclWithIssue,
                                  DiagnosticIdentifierList Hashtags) {
  if (!Location.isValid())
    return false;

  if (!DeclWithIssue) {
    // FIXME: This defeats the purpose of passing DeclWithIssue to begin with.
    // If this branch is ever hit, we're re-doing all the work we've already
    // done as well as perform a lot of work we'll never need.
    // Gladly, none of our on-by-default checkers currently need it.
    DeclWithIssue = ACtx.getTranslationUnitDecl();
  } else {
    // This is the fast path. However, we should still consider the topmost
    // declaration that isn't TranslationUnitDecl, because we should respect
    // attributes on the entire declaration chain.
    while (true) {

      // Template specializations (e.g., Wrapper<int>) should inherit