sammccall created this revision.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay, 
ioeric, ilya-biryukov, kbarton, nemanjai.

based on https://reviews.llvm.org/D54259, with API updates to make everything 
build again.

Not ready for review, probably won't become ready in this explicit form.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D54261

Files:
  clang-query/Query.cpp
  clang-reorder-fields/ReorderFieldsAction.cpp
  clang-tidy/abseil/RedundantStrcatCallsCheck.cpp
  clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp
  clang-tidy/bugprone/MultipleStatementMacroCheck.cpp
  clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp
  clang-tidy/bugprone/UnusedRaiiCheck.cpp
  clang-tidy/bugprone/UseAfterMoveCheck.cpp
  clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp
  clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
  clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h
  clang-tidy/google/AvoidCStyleCastsCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tidy/modernize/LoopConvertCheck.h
  clang-tidy/modernize/MakeSmartPtrCheck.cpp
  clang-tidy/modernize/MakeSmartPtrCheck.h
  clang-tidy/modernize/UseEqualsDefaultCheck.cpp
  clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tidy/performance/ForRangeCopyCheck.cpp
  clang-tidy/performance/ForRangeCopyCheck.h
  clang-tidy/performance/InefficientVectorOperationCheck.cpp
  clang-tidy/performance/UnnecessaryCopyInitialization.cpp
  clang-tidy/performance/UnnecessaryCopyInitialization.h
  clang-tidy/performance/UnnecessaryValueParamCheck.cpp
  clang-tidy/readability/ImplicitBoolConversionCheck.cpp
  clang-tidy/readability/ImplicitBoolConversionCheck.h
  clang-tidy/readability/MagicNumbersCheck.cpp
  clang-tidy/readability/MisleadingIndentationCheck.cpp
  clang-tidy/readability/MisleadingIndentationCheck.h
  clang-tidy/readability/RedundantDeclarationCheck.cpp
  clang-tidy/utils/ASTUtils.cpp
  clang-tidy/utils/ASTUtils.h
  clang-tidy/utils/DeclRefExprUtils.cpp
  clang-tidy/utils/DeclRefExprUtils.h
  clang-tidy/utils/ExprSequence.cpp
  clang-tidy/utils/ExprSequence.h
  clang-tidy/utils/NamespaceAliaser.cpp
  clang-tidy/utils/NamespaceAliaser.h
  clang-tidy/utils/UsingInserter.cpp
  clang-tidy/utils/UsingInserter.h
  clangd/ClangdUnit.cpp
  clangd/CodeComplete.cpp
  unittests/clang-tidy/NamespaceAliaserTest.cpp
  unittests/clang-tidy/UsingInserterTest.cpp

Index: unittests/clang-tidy/UsingInserterTest.cpp
===================================================================
--- unittests/clang-tidy/UsingInserterTest.cpp
+++ unittests/clang-tidy/UsingInserterTest.cpp
@@ -35,16 +35,17 @@
 
     const auto *Call = Result.Nodes.getNodeAs<clang::CallExpr>("foo");
     assert(Call != nullptr && "Did not find node \"foo\"");
-    auto Hint =
-        Inserter->createUsingDeclaration(*Result.Context, *Call, "::foo::func");
+    auto Hint = Inserter->createUsingDeclaration(
+        *Result.Context, *Result.Bounds, *Call, "::foo::func");
 
     if (Hint.hasValue())
       diag(Call->getBeginLoc(), "Fix for testing") << Hint.getValue();
 
     diag(Call->getBeginLoc(), "insert call")
         << clang::FixItHint::CreateReplacement(
                Call->getCallee()->getSourceRange(),
-               Inserter->getShortName(*Result.Context, *Call, "::foo::func"));
+               Inserter->getShortName(*Result.Context, *Result.Bounds, *Call,
+                                      "::foo::func"));
   }
 
 private:
Index: unittests/clang-tidy/NamespaceAliaserTest.cpp
===================================================================
--- unittests/clang-tidy/NamespaceAliaserTest.cpp
+++ unittests/clang-tidy/NamespaceAliaserTest.cpp
@@ -33,14 +33,16 @@
 
     const auto *Call = Result.Nodes.getNodeAs<CallExpr>("foo");
     assert(Call != nullptr && "Did not find node \"foo\"");
-    auto Hint = Aliaser->createAlias(*Result.Context, *Call, "::foo::bar",
-                                     {"b", "some_alias"});
+    auto Hint = Aliaser->createAlias(*Result.Context, *Result.Bounds, *Call,
+                                     "::foo::bar", {"b", "some_alias"});
     if (Hint.hasValue())
       diag(Call->getBeginLoc(), "Fix for testing") << Hint.getValue();
 
     diag(Call->getBeginLoc(), "insert call") << FixItHint::CreateInsertion(
         Call->getBeginLoc(),
-        Aliaser->getNamespaceName(*Result.Context, *Call, "::foo::bar") + "::");
+        Aliaser->getNamespaceName(*Result.Context, *Result.Bounds, *Call,
+                                  "::foo::bar") +
+            "::");
   }
 
 private:
Index: clangd/CodeComplete.cpp
===================================================================
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -36,7 +36,6 @@
 #include "index/Index.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclBase.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Format/Format.h"
@@ -1610,14 +1609,18 @@
 }
 
 bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx) {
-  using namespace clang::ast_matchers;
-  auto InTopLevelScope = hasDeclContext(
-      anyOf(namespaceDecl(), translationUnitDecl(), linkageSpecDecl()));
-  return !match(decl(anyOf(InTopLevelScope,
-                           hasDeclContext(
-                               enumDecl(InTopLevelScope, unless(isScoped()))))),
-                ND, ASTCtx)
-              .empty();
+  auto *DC = ND.getDeclContext();
+  if (auto* Enum = dyn_cast<EnumDecl>(DC))
+    if (!Enum->isScoped())
+      DC = Enum->getDeclContext();
+  switch (DC->getDeclKind()) {
+    case Decl::Namespace:
+    case Decl::TranslationUnit:
+    case Decl::LinkageSpec:
+      return true;
+    default:
+      return false;
+  }
 }
 
 CompletionItem CodeCompletion::render(const CodeCompleteOptions &Opts) const {
Index: clangd/ClangdUnit.cpp
===================================================================
--- clangd/ClangdUnit.cpp
+++ clangd/ClangdUnit.cpp
@@ -160,12 +160,7 @@
     for (const auto &E : tidy::ClangTidyModuleRegistry::entries())
       E.instantiate()->addCheckFactories(CTFactories);
     auto CTOpts = tidy::ClangTidyOptions::getDefaults();
-    // FIXME: this needs to be configurable, and we need to support .clang-tidy
-    // files and other options providers.
-    // There is an important bug to fix before turning on arbitrary checks:
-    // we must restrict the AST parent map to the current file for performance.
-    // The placeholder check here does not use hasAncestor() so is unaffected.
-    CTOpts.Checks = "bugprone-sizeof-expression";
+    CTOpts.Checks = "*";
     CTContext.emplace(llvm::make_unique<tidy::DefaultOptionsProvider>(
         tidy::ClangTidyGlobalOptions(), CTOpts));
     CTContext->setDiagnosticsEngine(&Clang->getDiagnostics());
@@ -192,7 +187,8 @@
     // Run the AST-dependent part of the clang-tidy checks.
     // (The preprocessor part ran already, via PPCallbacks).
     trace::Span Tracer("ClangTidyMatch");
-    CTFinder.matchAST(Clang->getASTContext(), ParsedDecls);
+    CTFinder.matchAST(Clang->getASTContext(),
+                      *Clang->getASTContext().bounds(ParsedDecls));
   }
 
   // UnitDiagsConsumer is local, we can not store it in CompilerInstance that
Index: clang-tidy/utils/UsingInserter.h
===================================================================
--- clang-tidy/utils/UsingInserter.h
+++ clang-tidy/utils/UsingInserter.h
@@ -10,6 +10,7 @@
 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_USINGINSERTER_H
 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_USINGINSERTER_H
 
+#include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Stmt.h"
 #include "clang/Basic/Diagnostic.h"
@@ -30,12 +31,13 @@
   // Creates a \p using declaration fixit. Returns ``llvm::None`` on error
   // or if the using declaration already exists.
   llvm::Optional<FixItHint>
-  createUsingDeclaration(ASTContext &Context, const Stmt &Statement,
-                         llvm::StringRef QualifiedName);
+  createUsingDeclaration(ASTContext &Context, ASTContext::Bounds &Bounds,
+                         const Stmt &Statement, llvm::StringRef QualifiedName);
 
   // Returns the unqualified version of the name if there is an
   // appropriate using declaration and the qualified name otherwise.
-  llvm::StringRef getShortName(ASTContext &Context, const Stmt &Statement,
+  llvm::StringRef getShortName(ASTContext &Context, ASTContext::Bounds &Bounds,
+                               const Stmt &Statement,
                                llvm::StringRef QualifiedName);
 
 private:
Index: clang-tidy/utils/UsingInserter.cpp
===================================================================
--- clang-tidy/utils/UsingInserter.cpp
+++ clang-tidy/utils/UsingInserter.cpp
@@ -31,9 +31,10 @@
     : SourceMgr(SourceMgr) {}
 
 Optional<FixItHint> UsingInserter::createUsingDeclaration(
-    ASTContext &Context, const Stmt &Statement, StringRef QualifiedName) {
+    ASTContext &Context, ASTContext::Bounds &Bounds, const Stmt &Statement, StringRef QualifiedName) {
   StringRef UnqualifiedName = getUnqualifiedName(QualifiedName);
-  const FunctionDecl *Function = getSurroundingFunction(Context, Statement);
+  const FunctionDecl *Function =
+      getSurroundingFunction(Context, Bounds, Statement);
   if (!Function)
     return None;
 
@@ -52,19 +53,19 @@
   bool AlreadyHasUsingDecl =
       !match(stmt(hasAncestor(decl(has(usingDecl(hasAnyUsingShadowDecl(
                  hasTargetDecl(hasName(QualifiedName.str())))))))),
-             Statement, Context)
+             Statement, Context, Bounds)
            .empty();
   if (AlreadyHasUsingDecl) {
     AddedUsing.emplace(NameInFunction(Function, QualifiedName.str()));
     return None;
   }
   // Find conflicting declarations and references.
   auto ConflictingDecl = namedDecl(hasName(UnqualifiedName));
   bool HasConflictingDeclaration =
-      !match(findAll(ConflictingDecl), *Function, Context).empty();
-  bool HasConflictingDeclRef =
-      !match(findAll(declRefExpr(to(ConflictingDecl))), *Function, Context)
-           .empty();
+      !match(findAll(ConflictingDecl), *Function, Context, Bounds).empty();
+  bool HasConflictingDeclRef = !match(findAll(declRefExpr(to(ConflictingDecl))),
+                                      *Function, Context, Bounds)
+                                    .empty();
   if (HasConflictingDeclaration || HasConflictingDeclRef)
     return None;
 
@@ -76,9 +77,11 @@
 }
 
 StringRef UsingInserter::getShortName(ASTContext &Context,
+                                      ASTContext::Bounds &Bounds,
                                       const Stmt &Statement,
                                       StringRef QualifiedName) {
-  const FunctionDecl *Function = getSurroundingFunction(Context, Statement);
+  const FunctionDecl *Function =
+      getSurroundingFunction(Context, Bounds, Statement);
   if (AddedUsing.count(NameInFunction(Function, QualifiedName.str())) != 0)
     return getUnqualifiedName(QualifiedName);
   return QualifiedName;
Index: clang-tidy/utils/NamespaceAliaser.h
===================================================================
--- clang-tidy/utils/NamespaceAliaser.h
+++ clang-tidy/utils/NamespaceAliaser.h
@@ -30,13 +30,14 @@
   // Statement. Picks the first available name from \p Abbreviations.
   // Returns ``llvm::None`` if an alias already exists or there is an error.
   llvm::Optional<FixItHint>
-  createAlias(ASTContext &Context, const Stmt &Statement,
-              llvm::StringRef Namespace,
+  createAlias(ASTContext &Context, ASTContext::Bounds &Bounds,
+              const Stmt &Statement, llvm::StringRef Namespace,
               const std::vector<std::string> &Abbreviations);
 
   // Get an alias name for \p Namespace valid at \p Statement. Returns \p
   // Namespace if there is no alias.
-  std::string getNamespaceName(ASTContext &Context, const Stmt &Statement,
+  std::string getNamespaceName(ASTContext &Context, ASTContext::Bounds &Bounds,
+                               const Stmt &Statement,
                                llvm::StringRef Namespace) const;
 
 private:
Index: clang-tidy/utils/NamespaceAliaser.cpp
===================================================================
--- clang-tidy/utils/NamespaceAliaser.cpp
+++ clang-tidy/utils/NamespaceAliaser.cpp
@@ -28,10 +28,10 @@
 }
 
 Optional<FixItHint>
-NamespaceAliaser::createAlias(ASTContext &Context, const Stmt &Statement,
-                              StringRef Namespace,
+NamespaceAliaser::createAlias(ASTContext &Context, ASTContext::Bounds &Bounds,
+                              const Stmt &Statement, StringRef Namespace,
                               const std::vector<std::string> &Abbreviations) {
-  const FunctionDecl *Function = getSurroundingFunction(Context, Statement);
+  const FunctionDecl *Function = getSurroundingFunction(Context, Bounds, Statement);
   if (!Function || !Function->hasBody())
     return None;
 
@@ -48,7 +48,7 @@
       match(functionDecl(hasBody(compoundStmt(has(declStmt(
                 has(namespaceAliasDecl(hasTargetNamespace(hasName(Namespace)))
                         .bind("alias"))))))),
-            *Function, Context));
+            *Function, Context, Bounds));
 
   if (ExistingAlias != nullptr) {
     AddedAliases[Function][Namespace.str()] = ExistingAlias->getName().str();
@@ -58,10 +58,10 @@
   for (const auto &Abbreviation : Abbreviations) {
     DeclarationMatcher ConflictMatcher = namedDecl(hasName(Abbreviation));
     const auto HasConflictingChildren =
-        !match(findAll(ConflictMatcher), *Function, Context).empty();
+        !match(findAll(ConflictMatcher), *Function, Context, Bounds).empty();
     const auto HasConflictingAncestors =
         !match(functionDecl(hasAncestor(decl(has(ConflictMatcher)))), *Function,
-               Context)
+               Context, Bounds)
              .empty();
     if (HasConflictingAncestors || HasConflictingChildren)
       continue;
@@ -80,9 +80,10 @@
 }
 
 std::string NamespaceAliaser::getNamespaceName(ASTContext &Context,
+                                               ASTContext::Bounds &Bounds,
                                                const Stmt &Statement,
                                                StringRef Namespace) const {
-  const auto *Function = getSurroundingFunction(Context, Statement);
+  const auto *Function = getSurroundingFunction(Context, Bounds, Statement);
   auto FunctionAliases = AddedAliases.find(Function);
   if (FunctionAliases != AddedAliases.end()) {
     if (FunctionAliases->second.count(Namespace) != 0) {
Index: clang-tidy/utils/ExprSequence.h
===================================================================
--- clang-tidy/utils/ExprSequence.h
+++ clang-tidy/utils/ExprSequence.h
@@ -70,7 +70,8 @@
 public:
   /// Initializes this `ExprSequence` with sequence information for the given
   /// `CFG`. `Root` is the root statement the CFG was built from.
-  ExprSequence(const CFG *TheCFG, const Stmt *Root, ASTContext *TheContext);
+  ExprSequence(const CFG *TheCFG, const Stmt *Root, ASTContext *TheContext,
+               ASTContext::Bounds *Bounds);
 
   /// Returns whether \p Before is sequenced before \p After.
   bool inSequence(const Stmt *Before, const Stmt *After) const;
@@ -94,6 +95,7 @@
   const Stmt *resolveSyntheticStmt(const Stmt *S) const;
 
   ASTContext *Context;
+  ASTContext::Bounds *Bounds;
   const Stmt *Root;
 
   llvm::DenseMap<const Stmt *, const Stmt *> SyntheticStmtSourceMap;
@@ -105,15 +107,16 @@
 class StmtToBlockMap {
 public:
   /// Initializes the map for the given `CFG`.
-  StmtToBlockMap(const CFG *TheCFG, ASTContext *TheContext);
+  StmtToBlockMap(const CFG *TheCFG, ASTContext *TheContext, ASTContext::Bounds *Bounds);
 
   /// Returns the block that \p S is contained in. Some `Stmt`s may be contained
   /// in more than one `CFGBlock`; in this case, this function returns the
   /// innermost block (i.e. the one that is furthest from the root of the tree).
   const CFGBlock *blockContainingStmt(const Stmt *S) const;
 
 private:
   ASTContext *Context;
+  ASTContext::Bounds *Bounds;
 
   llvm::DenseMap<const Stmt *, const CFGBlock *> Map;
 };
Index: clang-tidy/utils/ExprSequence.cpp
===================================================================
--- clang-tidy/utils/ExprSequence.cpp
+++ clang-tidy/utils/ExprSequence.cpp
@@ -26,10 +26,11 @@
 // and semantic forms of InitListExpr, and the parent-child relationships are
 // different between the two forms.
 static SmallVector<const Stmt *, 1> getParentStmts(const Stmt *S,
-                                                   ASTContext *Context) {
+                                                   ASTContext *Context,
+                                                   ASTContext::Bounds *Bounds) {
   SmallVector<const Stmt *, 1> Result;
 
-  ASTContext::DynTypedNodeList Parents = Context->getParents(*S);
+  ASTContext::DynTypedNodeList Parents = Context->getParents(*S, *Bounds);
 
   SmallVector<ast_type_traits::DynTypedNode, 1> NodesToProcess(Parents.begin(),
                                                                Parents.end());
@@ -41,7 +42,7 @@
     if (const auto *S = Node.get<Stmt>()) {
       Result.push_back(S);
     } else {
-      Parents = Context->getParents(Node);
+      Parents = Context->getParents(Node, *Bounds);
       NodesToProcess.append(Parents.begin(), Parents.end());
     }
   }
@@ -51,21 +52,21 @@
 
 namespace {
 bool isDescendantOrEqual(const Stmt *Descendant, const Stmt *Ancestor,
-                         ASTContext *Context) {
+                         ASTContext *Context, ASTContext::Bounds *Bounds) {
   if (Descendant == Ancestor)
     return true;
-  for (const Stmt *Parent : getParentStmts(Descendant, Context)) {
-    if (isDescendantOrEqual(Parent, Ancestor, Context))
+  for (const Stmt *Parent : getParentStmts(Descendant, Context, Bounds)) {
+    if (isDescendantOrEqual(Parent, Ancestor, Context, Bounds))
       return true;
   }
 
   return false;
 }
 }
 
 ExprSequence::ExprSequence(const CFG *TheCFG, const Stmt *Root,
-                           ASTContext *TheContext)
-    : Context(TheContext), Root(Root) {
+                           ASTContext *TheContext, ASTContext::Bounds *Bounds)
+    : Context(TheContext), Bounds(Bounds), Root(Root) {
   for (const auto &SyntheticStmt : TheCFG->synthetic_stmts()) {
     SyntheticStmtSourceMap[SyntheticStmt.first] = SyntheticStmt.second;
   }
@@ -79,13 +80,13 @@
   // chain of successors, we know that 'After' is sequenced after 'Before'.
   for (const Stmt *Successor = getSequenceSuccessor(Before); Successor;
        Successor = getSequenceSuccessor(Successor)) {
-    if (isDescendantOrEqual(After, Successor, Context))
+    if (isDescendantOrEqual(After, Successor, Context, Bounds))
       return true;
   }
 
   // If 'After' is a parent of 'Before' or is sequenced after one of these
   // parents, we know that it is sequenced after 'Before'.
-  for (const Stmt *Parent : getParentStmts(Before, Context)) {
+  for (const Stmt *Parent : getParentStmts(Before, Context, Bounds)) {
     if (Parent == After || inSequence(Parent, After))
       return true;
   }
@@ -99,10 +100,10 @@
 }
 
 const Stmt *ExprSequence::getSequenceSuccessor(const Stmt *S) const {
-  for (const Stmt *Parent : getParentStmts(S, Context)) {
+  for (const Stmt *Parent : getParentStmts(S, Context, Bounds)) {
     // If a statement has multiple parents, make sure we're using the parent
     // that lies within the sub-tree under Root.
-    if (!isDescendantOrEqual(Parent, Root, Context))
+    if (!isDescendantOrEqual(Parent, Root, Context, Bounds))
       continue;
 
     if (const auto *BO = dyn_cast<BinaryOperator>(Parent)) {
@@ -177,8 +178,8 @@
   return S;
 }
 
-StmtToBlockMap::StmtToBlockMap(const CFG *TheCFG, ASTContext *TheContext)
-    : Context(TheContext) {
+StmtToBlockMap::StmtToBlockMap(const CFG *TheCFG, ASTContext *TheContext, ASTContext::Bounds *Bounds)
+    : Context(TheContext),Bounds(Bounds) {
   for (const auto *B : *TheCFG) {
     for (const auto &Elem : *B) {
       if (Optional<CFGStmt> S = Elem.getAs<CFGStmt>())
@@ -189,7 +190,7 @@
 
 const CFGBlock *StmtToBlockMap::blockContainingStmt(const Stmt *S) const {
   while (!Map.count(S)) {
-    SmallVector<const Stmt *, 1> Parents = getParentStmts(S, Context);
+    SmallVector<const Stmt *, 1> Parents = getParentStmts(S, Context, Bounds);
     if (Parents.empty())
       return nullptr;
     S = Parents[0];
Index: clang-tidy/utils/DeclRefExprUtils.h
===================================================================
--- clang-tidy/utils/DeclRefExprUtils.h
+++ clang-tidy/utils/DeclRefExprUtils.h
@@ -26,37 +26,37 @@
 /// variable or the variable is a const reference or value argument to a
 /// ``callExpr()``.
 bool isOnlyUsedAsConst(const VarDecl &Var, const Stmt &Stmt,
-                       ASTContext &Context);
+                       ASTContext &Context, ASTContext::Bounds &Bounds);
 
 /// Returns set of all ``DeclRefExprs`` to ``VarDecl`` within ``Stmt``.
 llvm::SmallPtrSet<const DeclRefExpr *, 16>
-allDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt, ASTContext &Context);
+allDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt, ASTContext &Context, ASTContext::Bounds &Bounds);
 
 /// Returns set of all ``DeclRefExprs`` to ``VarDecl`` within ``Decl``.
 llvm::SmallPtrSet<const DeclRefExpr *, 16>
-allDeclRefExprs(const VarDecl &VarDecl, const Decl &Decl, ASTContext &Context);
+allDeclRefExprs(const VarDecl &VarDecl, const Decl &Decl, ASTContext &Context, ASTContext::Bounds &Bounds);
 
 /// Returns set of all ``DeclRefExprs`` to ``VarDecl`` within ``Stmt`` where
 /// ``VarDecl`` is guaranteed to be accessed in a const fashion.
 llvm::SmallPtrSet<const DeclRefExpr *, 16>
 constReferenceDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt,
-                           ASTContext &Context);
+                           ASTContext &Context, ASTContext::Bounds &Bounds);
 
 /// Returns set of all ``DeclRefExprs`` to ``VarDecl`` within ``Decl`` where
 /// ``VarDecl`` is guaranteed to be accessed in a const fashion.
 llvm::SmallPtrSet<const DeclRefExpr *, 16>
 constReferenceDeclRefExprs(const VarDecl &VarDecl, const Decl &Decl,
-                           ASTContext &Context);
+                           ASTContext &Context, ASTContext::Bounds &Bounds);
 
 /// Returns ``true`` if ``DeclRefExpr`` is the argument of a copy-constructor
 /// call expression within ``Decl``.
 bool isCopyConstructorArgument(const DeclRefExpr &DeclRef, const Decl &Decl,
-                               ASTContext &Context);
+                               ASTContext &Context, ASTContext::Bounds &Bounds);
 
 /// Returns ``true`` if ``DeclRefExpr`` is the argument of a copy-assignment
 /// operator CallExpr within ``Decl``.
 bool isCopyAssignmentArgument(const DeclRefExpr &DeclRef, const Decl &Decl,
-                              ASTContext &Context);
+                              ASTContext &Context, ASTContext::Bounds &Bounds);
 
 } // namespace decl_ref_expr
 } // namespace utils
Index: clang-tidy/utils/DeclRefExprUtils.cpp
===================================================================
--- clang-tidy/utils/DeclRefExprUtils.cpp
+++ clang-tidy/utils/DeclRefExprUtils.cpp
@@ -44,7 +44,7 @@
 // is the a const reference or value argument to a CallExpr or CXXConstructExpr.
 SmallPtrSet<const DeclRefExpr *, 16>
 constReferenceDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt,
-                           ASTContext &Context) {
+                           ASTContext &Context, ASTContext::Bounds &Bounds) {
   auto DeclRefToVar =
       declRefExpr(to(varDecl(equalsNode(&VarDecl)))).bind("declRef");
   auto ConstMethodCallee = callee(cxxMethodDecl(isConst()));
@@ -55,27 +55,28 @@
       findAll(expr(anyOf(cxxMemberCallExpr(ConstMethodCallee, on(DeclRefToVar)),
                          cxxOperatorCallExpr(ConstMethodCallee,
                                              hasArgument(0, DeclRefToVar))))),
-      Stmt, Context);
+      Stmt, Context, Bounds);
   SmallPtrSet<const DeclRefExpr *, 16> DeclRefs;
   extractNodesByIdTo(Matches, "declRef", DeclRefs);
   auto ConstReferenceOrValue =
       qualType(anyOf(referenceType(pointee(qualType(isConstQualified()))),
                      unless(anyOf(referenceType(), pointerType()))));
   auto UsedAsConstRefOrValueArg = forEachArgumentWithParam(
       DeclRefToVar, parmVarDecl(hasType(ConstReferenceOrValue)));
-  Matches = match(findAll(callExpr(UsedAsConstRefOrValueArg)), Stmt, Context);
-  extractNodesByIdTo(Matches, "declRef", DeclRefs);
   Matches =
-      match(findAll(cxxConstructExpr(UsedAsConstRefOrValueArg)), Stmt, Context);
+      match(findAll(callExpr(UsedAsConstRefOrValueArg)), Stmt, Context, Bounds);
+  extractNodesByIdTo(Matches, "declRef", DeclRefs);
+  Matches = match(findAll(cxxConstructExpr(UsedAsConstRefOrValueArg)), Stmt,
+                  Context, Bounds);
   extractNodesByIdTo(Matches, "declRef", DeclRefs);
   return DeclRefs;
 }
 
 // Finds all DeclRefExprs where a const method is called on VarDecl or VarDecl
 // is the a const reference or value argument to a CallExpr or CXXConstructExpr.
 SmallPtrSet<const DeclRefExpr *, 16>
 constReferenceDeclRefExprs(const VarDecl &VarDecl, const Decl &Decl,
-                           ASTContext &Context) {
+                           ASTContext &Context, ASTContext::Bounds &Bounds) {
   auto DeclRefToVar =
       declRefExpr(to(varDecl(equalsNode(&VarDecl)))).bind("declRef");
   auto ConstMethodCallee = callee(cxxMethodDecl(isConst()));
@@ -87,82 +88,83 @@
                 anyOf(cxxMemberCallExpr(ConstMethodCallee, on(DeclRefToVar)),
                       cxxOperatorCallExpr(ConstMethodCallee,
                                           hasArgument(0, DeclRefToVar)))))),
-            Decl, Context);
+            Decl, Context, Bounds);
   SmallPtrSet<const DeclRefExpr *, 16> DeclRefs;
   extractNodesByIdTo(Matches, "declRef", DeclRefs);
   auto ConstReferenceOrValue =
       qualType(anyOf(referenceType(pointee(qualType(isConstQualified()))),
                      unless(anyOf(referenceType(), pointerType()))));
   auto UsedAsConstRefOrValueArg = forEachArgumentWithParam(
       DeclRefToVar, parmVarDecl(hasType(ConstReferenceOrValue)));
   Matches = match(decl(forEachDescendant(callExpr(UsedAsConstRefOrValueArg))),
-                  Decl, Context);
+                  Decl, Context, Bounds);
   extractNodesByIdTo(Matches, "declRef", DeclRefs);
   Matches =
       match(decl(forEachDescendant(cxxConstructExpr(UsedAsConstRefOrValueArg))),
-            Decl, Context);
+            Decl, Context, Bounds);
   extractNodesByIdTo(Matches, "declRef", DeclRefs);
   return DeclRefs;
 }
 
 bool isOnlyUsedAsConst(const VarDecl &Var, const Stmt &Stmt,
-                       ASTContext &Context) {
+                       ASTContext &Context, ASTContext::Bounds &Bounds) {
   // Collect all DeclRefExprs to the loop variable and all CallExprs and
   // CXXConstructExprs where the loop variable is used as argument to a const
   // reference parameter.
   // If the difference is empty it is safe for the loop variable to be a const
   // reference.
-  auto AllDeclRefs = allDeclRefExprs(Var, Stmt, Context);
-  auto ConstReferenceDeclRefs = constReferenceDeclRefExprs(Var, Stmt, Context);
+  auto AllDeclRefs = allDeclRefExprs(Var, Stmt, Context, Bounds);
+  auto ConstReferenceDeclRefs =
+      constReferenceDeclRefExprs(Var, Stmt, Context, Bounds);
   return isSetDifferenceEmpty(AllDeclRefs, ConstReferenceDeclRefs);
 }
 
 SmallPtrSet<const DeclRefExpr *, 16>
-allDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt, ASTContext &Context) {
+allDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt, ASTContext &Context, ASTContext::Bounds &Bounds) {
   auto Matches = match(
       findAll(declRefExpr(to(varDecl(equalsNode(&VarDecl)))).bind("declRef")),
-      Stmt, Context);
+      Stmt, Context, Bounds);
   SmallPtrSet<const DeclRefExpr *, 16> DeclRefs;
   extractNodesByIdTo(Matches, "declRef", DeclRefs);
   return DeclRefs;
 }
 
 SmallPtrSet<const DeclRefExpr *, 16>
-allDeclRefExprs(const VarDecl &VarDecl, const Decl &Decl, ASTContext &Context) {
+allDeclRefExprs(const VarDecl &VarDecl, const Decl &Decl, ASTContext &Context, ASTContext::Bounds &Bounds) {
   auto Matches = match(
       decl(forEachDescendant(
           declRefExpr(to(varDecl(equalsNode(&VarDecl)))).bind("declRef"))),
-      Decl, Context);
+      Decl, Context, Bounds);
   SmallPtrSet<const DeclRefExpr *, 16> DeclRefs;
   extractNodesByIdTo(Matches, "declRef", DeclRefs);
   return DeclRefs;
 }
 
 bool isCopyConstructorArgument(const DeclRefExpr &DeclRef, const Decl &Decl,
-                               ASTContext &Context) {
+                               ASTContext &Context, ASTContext::Bounds &Bounds) {
   auto UsedAsConstRefArg = forEachArgumentWithParam(
       declRefExpr(equalsNode(&DeclRef)),
       parmVarDecl(hasType(matchers::isReferenceToConst())));
   auto Matches = match(
       decl(hasDescendant(
           cxxConstructExpr(UsedAsConstRefArg, hasDeclaration(cxxConstructorDecl(
                                                   isCopyConstructor())))
               .bind("constructExpr"))),
-      Decl, Context);
+      Decl, Context, Bounds);
   return !Matches.empty();
 }
 
 bool isCopyAssignmentArgument(const DeclRefExpr &DeclRef, const Decl &Decl,
-                              ASTContext &Context) {
+                              ASTContext &Context, ASTContext::Bounds &Bounds) {
   auto UsedAsConstRefArg = forEachArgumentWithParam(
       declRefExpr(equalsNode(&DeclRef)),
       parmVarDecl(hasType(matchers::isReferenceToConst())));
   auto Matches = match(
       decl(hasDescendant(
           cxxOperatorCallExpr(UsedAsConstRefArg, hasOverloadedOperatorName("="),
                               callee(cxxMethodDecl(isCopyAssignmentOperator())))
               .bind("operatorCallExpr"))),
-      Decl, Context);
+      Decl, Context, Bounds);
   return !Matches.empty();
 }
 
Index: clang-tidy/utils/ASTUtils.h
===================================================================
--- clang-tidy/utils/ASTUtils.h
+++ clang-tidy/utils/ASTUtils.h
@@ -17,6 +17,7 @@
 namespace utils {
 // Returns the (closest) Function declaration surrounding |Statement| or NULL.
 const FunctionDecl *getSurroundingFunction(ASTContext &Context,
+                                           ASTContext::Bounds &Bounds,
                                            const Stmt &Statement);
 // Determine whether Expr is a Binary or Ternary expression.
 bool IsBinaryOrTernary(const Expr *E);
Index: clang-tidy/utils/ASTUtils.cpp
===================================================================
--- clang-tidy/utils/ASTUtils.cpp
+++ clang-tidy/utils/ASTUtils.cpp
@@ -19,10 +19,11 @@
 using namespace ast_matchers;
 
 const FunctionDecl *getSurroundingFunction(ASTContext &Context,
+                                           ASTContext::Bounds &Bounds,
                                            const Stmt &Statement) {
   return selectFirst<const FunctionDecl>(
       "function", match(stmt(hasAncestor(functionDecl().bind("function"))),
-                        Statement, Context));
+                        Statement, Context, Bounds));
 }
 
 bool IsBinaryOrTernary(const Expr *E) {
Index: clang-tidy/readability/RedundantDeclarationCheck.cpp
===================================================================
--- clang-tidy/readability/RedundantDeclarationCheck.cpp
+++ clang-tidy/readability/RedundantDeclarationCheck.cpp
@@ -45,7 +45,7 @@
       (D->getLocation().isMacroID() || Prev->getLocation().isMacroID()))
     return;
   // Don't complain when the previous declaration is a friend declaration.
-  for (const auto &Parent : Result.Context->getParents(*Prev))
+  for (const auto &Parent : Result.Context->getParents(*Prev, *Result.Bounds))
     if (Parent.get<FriendDecl>())
       return;
 
Index: clang-tidy/readability/MisleadingIndentationCheck.h
===================================================================
--- clang-tidy/readability/MisleadingIndentationCheck.h
+++ clang-tidy/readability/MisleadingIndentationCheck.h
@@ -31,7 +31,7 @@
 
 private:
   void danglingElseCheck(const SourceManager &SM, ASTContext *Context,
-                         const IfStmt *If);
+                         ASTContext::Bounds *Bounds, const IfStmt *If);
   void missingBracesCheck(const SourceManager &SM, const CompoundStmt *CStmt);
 };
 
Index: clang-tidy/readability/MisleadingIndentationCheck.cpp
===================================================================
--- clang-tidy/readability/MisleadingIndentationCheck.cpp
+++ clang-tidy/readability/MisleadingIndentationCheck.cpp
@@ -18,8 +18,10 @@
 namespace readability {
 
 static const IfStmt *getPrecedingIf(const SourceManager &SM,
-                                    ASTContext *Context, const IfStmt *If) {
-  auto parents = Context->getParents(*If);
+                                    ASTContext *Context,
+                                    ASTContext::Bounds *Bounds,
+                                    const IfStmt *If) {
+  auto parents = Context->getParents(*If, *Bounds);
   if (parents.size() != 1)
     return nullptr;
   if (const auto *PrecedingIf = parents[0].get<IfStmt>()) {
@@ -33,6 +35,7 @@
 
 void MisleadingIndentationCheck::danglingElseCheck(const SourceManager &SM,
                                                    ASTContext *Context,
+                                                   ASTContext::Bounds *Bounds,
                                                    const IfStmt *If) {
   SourceLocation IfLoc = If->getIfLoc();
   SourceLocation ElseLoc = If->getElseLoc();
@@ -45,8 +48,8 @@
     return;
 
   // Find location of first 'if' in a 'if else if' chain.
-  for (auto PrecedingIf = getPrecedingIf(SM, Context, If); PrecedingIf;
-       PrecedingIf = getPrecedingIf(SM, Context, PrecedingIf))
+  for (auto PrecedingIf = getPrecedingIf(SM, Context, Bounds, If); PrecedingIf;
+       PrecedingIf = getPrecedingIf(SM, Context, Bounds, PrecedingIf))
     IfLoc = PrecedingIf->getIfLoc();
 
   if (SM.getExpansionColumnNumber(IfLoc) !=
@@ -112,7 +115,7 @@
 
 void MisleadingIndentationCheck::check(const MatchFinder::MatchResult &Result) {
   if (const auto *If = Result.Nodes.getNodeAs<IfStmt>("if"))
-    danglingElseCheck(*Result.SourceManager, Result.Context, If);
+    danglingElseCheck(*Result.SourceManager, Result.Context, Result.Bounds, If);
 
   if (const auto *CStmt = Result.Nodes.getNodeAs<CompoundStmt>("compound"))
     missingBracesCheck(*Result.SourceManager, CStmt);
Index: clang-tidy/readability/MagicNumbersCheck.cpp
===================================================================
--- clang-tidy/readability/MagicNumbersCheck.cpp
+++ clang-tidy/readability/MagicNumbersCheck.cpp
@@ -38,7 +38,7 @@
   if (Node.get<clang::EnumConstantDecl>() != nullptr)
     return true;
 
-  return llvm::any_of(Result.Context->getParents(Node),
+  return llvm::any_of(Result.Context->getParents(Node, *Result.Bounds),
                       [&Result](const DynTypedNode &Parent) {
                         return isUsedToInitializeAConstant(Result, Parent);
                       });
@@ -111,7 +111,7 @@
 bool MagicNumbersCheck::isConstant(const MatchFinder::MatchResult &Result,
                                    const Expr &ExprResult) const {
   return llvm::any_of(
-      Result.Context->getParents(ExprResult),
+      Result.Context->getParents(ExprResult, *Result.Bounds),
       [&Result](const DynTypedNode &Parent) {
         return isUsedToInitializeAConstant(Result, Parent) ||
                // Ignore this instance, because this match reports the location
Index: clang-tidy/readability/ImplicitBoolConversionCheck.h
===================================================================
--- clang-tidy/readability/ImplicitBoolConversionCheck.h
+++ clang-tidy/readability/ImplicitBoolConversionCheck.h
@@ -30,7 +30,8 @@
 
 private:
   void handleCastToBool(const ImplicitCastExpr *CastExpression,
-                        const Stmt *ParentStatement, ASTContext &Context);
+                        const Stmt *ParentStatement, ASTContext &Context,
+                        ASTContext::Bounds &Bounds);
   void handleCastFromBool(const ImplicitCastExpr *CastExpression,
                           const ImplicitCastExpr *FurtherImplicitCastExpression,
                           ASTContext &Context);
Index: clang-tidy/readability/ImplicitBoolConversionCheck.cpp
===================================================================
--- clang-tidy/readability/ImplicitBoolConversionCheck.cpp
+++ clang-tidy/readability/ImplicitBoolConversionCheck.cpp
@@ -91,7 +91,7 @@
 
 void fixGenericExprCastToBool(DiagnosticBuilder &Diag,
                               const ImplicitCastExpr *Cast, const Stmt *Parent,
-                              ASTContext &Context) {
+                              ASTContext &Context, ASTContext::Bounds &Bounds) {
   // In case of expressions like (! integer), we should remove the redundant not
   // operator and use inverted comparison (integer == 0).
   bool InvertComparison =
@@ -103,7 +103,7 @@
     Diag << FixItHint::CreateRemoval(
         CharSourceRange::getCharRange(ParentStartLoc, ParentEndLoc));
 
-    Parent = Context.getParents(*Parent)[0].get<Stmt>();
+    Parent = Context.getParents(*Parent, Bounds)[0].get<Stmt>();
   }
 
   const Expr *SubExpr = Cast->getSubExpr();
@@ -219,11 +219,11 @@
 }
 
 bool isCastAllowedInCondition(const ImplicitCastExpr *Cast,
-                              ASTContext &Context) {
+                              ASTContext &Context, ASTContext::Bounds &Bounds) {
   std::queue<const Stmt *> Q;
   Q.push(Cast);
   while (!Q.empty()) {
-    for (const auto &N : Context.getParents(*Q.front())) {
+    for (const auto &N : Context.getParents(*Q.front(), Bounds)) {
       const Stmt *S = N.get<Stmt>();
       if (!S)
         return false;
@@ -329,7 +329,8 @@
   if (const auto *CastToBool =
           Result.Nodes.getNodeAs<ImplicitCastExpr>("implicitCastToBool")) {
     const auto *Parent = Result.Nodes.getNodeAs<Stmt>("parentStmt");
-    return handleCastToBool(CastToBool, Parent, *Result.Context);
+    return handleCastToBool(CastToBool, Parent, *Result.Context,
+                            *Result.Bounds);
   }
 
   if (const auto *CastFromBool =
@@ -342,16 +343,17 @@
 
 void ImplicitBoolConversionCheck::handleCastToBool(const ImplicitCastExpr *Cast,
                                                    const Stmt *Parent,
-                                                   ASTContext &Context) {
+                                                   ASTContext &Context,
+                                                   ASTContext::Bounds &Bounds) {
   if (AllowPointerConditions &&
       (Cast->getCastKind() == CK_PointerToBoolean ||
        Cast->getCastKind() == CK_MemberPointerToBoolean) &&
-      isCastAllowedInCondition(Cast, Context)) {
+      isCastAllowedInCondition(Cast, Context, Bounds)) {
     return;
   }
 
   if (AllowIntegerConditions && Cast->getCastKind() == CK_IntegralToBoolean &&
-      isCastAllowedInCondition(Cast, Context)) {
+      isCastAllowedInCondition(Cast, Context, Bounds)) {
     return;
   }
 
@@ -363,7 +365,7 @@
   if (!EquivalentLiteral.empty()) {
     Diag << tooling::fixit::createReplacement(*Cast, EquivalentLiteral);
   } else {
-    fixGenericExprCastToBool(Diag, Cast, Parent, Context);
+    fixGenericExprCastToBool(Diag, Cast, Parent, Context, Bounds);
   }
 }
 
Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp
===================================================================
--- clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -33,21 +33,22 @@
 }
 
 bool isReferencedOutsideOfCallExpr(const FunctionDecl &Function,
-                                   ASTContext &Context) {
+                                   ASTContext &Context,
+                                   ASTContext::Bounds &Bounds) {
   auto Matches = match(declRefExpr(to(functionDecl(equalsNode(&Function))),
                                    unless(hasAncestor(callExpr()))),
-                       Context);
+                       Context, Bounds);
   return !Matches.empty();
 }
 
 bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Decl &Decl,
-                         ASTContext &Context) {
+                         ASTContext &Context, ASTContext::Bounds &Bounds) {
   auto Matches =
       match(decl(forEachDescendant(declRefExpr(
                 equalsNode(&DeclRef),
                 unless(hasAncestor(stmt(anyOf(forStmt(), cxxForRangeStmt(),
                                               whileStmt(), doStmt()))))))),
-            Decl, Context);
+            Decl, Context, Bounds);
   return Matches.empty();
 }
 
@@ -98,7 +99,8 @@
   const auto *Function = Result.Nodes.getNodeAs<FunctionDecl>("functionDecl");
 
   FunctionParmMutationAnalyzer &Analyzer =
-      MutationAnalyzers.try_emplace(Function, *Function, *Result.Context)
+      MutationAnalyzers
+          .try_emplace(Function, *Function, *Result.Context, *Result.Bounds)
           .first->second;
   if (Analyzer.isMutated(Param))
     return;
@@ -113,18 +115,18 @@
   // copy.
   if (!IsConstQualified) {
     auto AllDeclRefExprs = utils::decl_ref_expr::allDeclRefExprs(
-        *Param, *Function, *Result.Context);
+        *Param, *Function, *Result.Context, *Result.Bounds);
     if (AllDeclRefExprs.size() == 1) {
       auto CanonicalType = Param->getType().getCanonicalType();
       const auto &DeclRefExpr = **AllDeclRefExprs.begin();
 
-      if (!hasLoopStmtAncestor(DeclRefExpr, *Function, *Result.Context) &&
+      if (!hasLoopStmtAncestor(DeclRefExpr, *Function, *Result.Context, *Result.Bounds) &&
           ((utils::type_traits::hasNonTrivialMoveConstructor(CanonicalType) &&
             utils::decl_ref_expr::isCopyConstructorArgument(
-                DeclRefExpr, *Function, *Result.Context)) ||
+                DeclRefExpr, *Function, *Result.Context, *Result.Bounds)) ||
            (utils::type_traits::hasNonTrivialMoveAssignment(CanonicalType) &&
             utils::decl_ref_expr::isCopyAssignmentArgument(
-                DeclRefExpr, *Function, *Result.Context)))) {
+                DeclRefExpr, *Function, *Result.Context, *Result.Bounds)))) {
         handleMoveFix(*Param, DeclRefExpr, *Result.Context);
         return;
       }
@@ -152,7 +154,8 @@
   // 4. the function is an explicit template specialization.
   const auto *Method = llvm::dyn_cast<CXXMethodDecl>(Function);
   if (Param->getBeginLoc().isMacroID() || (Method && Method->isVirtual()) ||
-      isReferencedOutsideOfCallExpr(*Function, *Result.Context) ||
+      isReferencedOutsideOfCallExpr(*Function, *Result.Context,
+                                    *Result.Bounds) ||
       isExplicitTemplateSpecialization(*Function))
     return;
   for (const auto *FunctionDecl = Function; FunctionDecl != nullptr;
Index: clang-tidy/performance/UnnecessaryCopyInitialization.h
===================================================================
--- clang-tidy/performance/UnnecessaryCopyInitialization.h
+++ clang-tidy/performance/UnnecessaryCopyInitialization.h
@@ -34,10 +34,10 @@
 private:
   void handleCopyFromMethodReturn(const VarDecl &Var, const Stmt &BlockStmt,
                                   bool IssueFix, const VarDecl *ObjectArg,
-                                  ASTContext &Context);
+                                  ASTContext &Context, ASTContext::Bounds &Bounds);
   void handleCopyFromLocalVar(const VarDecl &NewVar, const VarDecl &OldVar,
                               const Stmt &BlockStmt, bool IssueFix,
-                              ASTContext &Context);
+                              ASTContext &Context, ASTContext::Bounds &Bounds);
   const std::vector<std::string> AllowedTypes;
 };
 
Index: clang-tidy/performance/UnnecessaryCopyInitialization.cpp
===================================================================
--- clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -112,21 +112,21 @@
 
   if (OldVar == nullptr) {
     handleCopyFromMethodReturn(*NewVar, *BlockStmt, IssueFix, ObjectArg,
-                               *Result.Context);
+                               *Result.Context, *Result.Bounds);
   } else {
     handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, IssueFix,
-                           *Result.Context);
+                           *Result.Context, *Result.Bounds);
   }
 }
 
 void UnnecessaryCopyInitialization::handleCopyFromMethodReturn(
     const VarDecl &Var, const Stmt &BlockStmt, bool IssueFix,
-    const VarDecl *ObjectArg, ASTContext &Context) {
+    const VarDecl *ObjectArg, ASTContext &Context, ASTContext::Bounds &Bounds) {
   bool IsConstQualified = Var.getType().isConstQualified();
-  if (!IsConstQualified && !isOnlyUsedAsConst(Var, BlockStmt, Context))
+  if (!IsConstQualified && !isOnlyUsedAsConst(Var, BlockStmt, Context, Bounds))
     return;
   if (ObjectArg != nullptr &&
-      !isOnlyUsedAsConst(*ObjectArg, BlockStmt, Context))
+      !isOnlyUsedAsConst(*ObjectArg, BlockStmt, Context, Bounds))
     return;
 
   auto Diagnostic =
@@ -144,9 +144,9 @@
 
 void UnnecessaryCopyInitialization::handleCopyFromLocalVar(
     const VarDecl &NewVar, const VarDecl &OldVar, const Stmt &BlockStmt,
-    bool IssueFix, ASTContext &Context) {
-  if (!isOnlyUsedAsConst(NewVar, BlockStmt, Context) ||
-      !isOnlyUsedAsConst(OldVar, BlockStmt, Context))
+    bool IssueFix, ASTContext &Context, ASTContext::Bounds &Bounds) {
+  if (!isOnlyUsedAsConst(NewVar, BlockStmt, Context, Bounds) ||
+      !isOnlyUsedAsConst(OldVar, BlockStmt, Context, Bounds))
     return;
 
   auto Diagnostic = diag(NewVar.getLocation(),
Index: clang-tidy/performance/InefficientVectorOperationCheck.cpp
===================================================================
--- clang-tidy/performance/InefficientVectorOperationCheck.cpp
+++ clang-tidy/performance/InefficientVectorOperationCheck.cpp
@@ -158,7 +158,7 @@
 
   llvm::SmallPtrSet<const DeclRefExpr *, 16> AllVectorVarRefs =
       utils::decl_ref_expr::allDeclRefExprs(*VectorVarDecl, *LoopParent,
-                                            *Context);
+                                            *Context, *Result.Bounds);
   for (const auto *Ref : AllVectorVarRefs) {
     // Skip cases where there are usages (defined as DeclRefExpr that refers to
     // "v") of vector variable `v` before the for loop. We consider these usages
Index: clang-tidy/performance/ForRangeCopyCheck.h
===================================================================
--- clang-tidy/performance/ForRangeCopyCheck.h
+++ clang-tidy/performance/ForRangeCopyCheck.h
@@ -37,7 +37,7 @@
   // reference argument. If so it suggests it be made a const reference.
   bool handleCopyIsOnlyConstReferenced(const VarDecl &LoopVar,
                                        const CXXForRangeStmt &ForRange,
-                                       ASTContext &Context);
+                                       ASTContext &, ASTContext::Bounds &);
 
   const bool WarnOnAllAutoCopies;
   const std::vector<std::string> AllowedTypes;
Index: clang-tidy/performance/ForRangeCopyCheck.cpp
===================================================================
--- clang-tidy/performance/ForRangeCopyCheck.cpp
+++ clang-tidy/performance/ForRangeCopyCheck.cpp
@@ -57,7 +57,8 @@
   if (handleConstValueCopy(*Var, *Result.Context))
     return;
   const auto *ForRange = Result.Nodes.getNodeAs<CXXForRangeStmt>("forRange");
-  handleCopyIsOnlyConstReferenced(*Var, *ForRange, *Result.Context);
+  handleCopyIsOnlyConstReferenced(*Var, *ForRange, *Result.Context,
+                                  *Result.Bounds);
 }
 
 bool ForRangeCopyCheck::handleConstValueCopy(const VarDecl &LoopVar,
@@ -85,7 +86,7 @@
 
 bool ForRangeCopyCheck::handleCopyIsOnlyConstReferenced(
     const VarDecl &LoopVar, const CXXForRangeStmt &ForRange,
-    ASTContext &Context) {
+    ASTContext &Context, ASTContext::Bounds &Bounds) {
   llvm::Optional<bool> Expensive =
       utils::type_traits::isExpensiveToCopy(LoopVar.getType(), Context);
   if (LoopVar.getType().isConstQualified() || !Expensive || !*Expensive)
@@ -98,9 +99,10 @@
   // Because the fix (changing to `const auto &`) will introduce an unused
   // compiler warning which can't be suppressed.
   // Since this case is very rare, it is safe to ignore it.
-  if (!ExprMutationAnalyzer(*ForRange.getBody(), Context).isMutated(&LoopVar) &&
+  if (!ExprMutationAnalyzer(*ForRange.getBody(), Context, Bounds)
+           .isMutated(&LoopVar) &&
       !utils::decl_ref_expr::allDeclRefExprs(LoopVar, *ForRange.getBody(),
-                                             Context)
+                                             Context, Bounds)
            .empty()) {
     diag(LoopVar.getLocation(),
          "loop variable is copied but only used as const reference; consider "
Index: clang-tidy/modernize/UseNullptrCheck.cpp
===================================================================
--- clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tidy/modernize/UseNullptrCheck.cpp
@@ -171,9 +171,9 @@
 /// ambiguities.
 class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> {
 public:
-  CastSequenceVisitor(ASTContext &Context, ArrayRef<StringRef> NullMacros,
-                      ClangTidyCheck &check)
-      : SM(Context.getSourceManager()), Context(Context),
+  CastSequenceVisitor(ASTContext &Context, ASTContext::Bounds &Bounds,
+                      ArrayRef<StringRef> NullMacros, ClangTidyCheck &check)
+      : SM(Context.getSourceManager()), Context(Context), Bounds(Bounds),
         NullMacros(NullMacros), Check(check), FirstSubExpr(nullptr),
         PruneSubtree(false) {}
 
@@ -419,7 +419,7 @@
     assert(MacroLoc.isFileID());
 
     while (true) {
-      const auto &Parents = Context.getParents(Start);
+      const auto &Parents = Context.getParents(Start, Bounds);
       if (Parents.empty())
         return false;
       if (Parents.size() > 1) {
@@ -458,6 +458,7 @@
 private:
   SourceManager &SM;
   ASTContext &Context;
+  ASTContext::Bounds &Bounds;
   ArrayRef<StringRef> NullMacros;
   ClangTidyCheck &Check;
   Expr *FirstSubExpr;
@@ -491,7 +492,7 @@
   // Given an implicit null-ptr cast or an explicit cast with an implicit
   // null-to-pointer cast within use CastSequenceVisitor to identify sequences
   // of explicit casts that can be converted into 'nullptr'.
-  CastSequenceVisitor(*Result.Context, NullMacros, *this)
+  CastSequenceVisitor(*Result.Context, *Result.Bounds, NullMacros, *this)
       .TraverseStmt(const_cast<CastExpr *>(NullCast));
 }
 
Index: clang-tidy/modernize/UseEqualsDefaultCheck.cpp
===================================================================
--- clang-tidy/modernize/UseEqualsDefaultCheck.cpp
+++ clang-tidy/modernize/UseEqualsDefaultCheck.cpp
@@ -58,6 +58,7 @@
 /// \brief Check that the given constructor has copy signature and that it
 /// copy-initializes all its bases and members.
 static bool isCopyConstructorAndCanBeDefaulted(ASTContext *Context,
+                                               ASTContext::Bounds *Bounds,
                                                const CXXConstructorDecl *Ctor) {
   // An explicitly-defaulted constructor cannot have default arguments.
   if (Ctor->getMinRequiredArguments() != 1)
@@ -83,7 +84,7 @@
                     argumentCountIs(1),
                     hasArgument(
                         0, declRefExpr(to(varDecl(equalsNode(Param))))))))))),
-            *Ctor, *Context)
+            *Ctor, *Context, *Bounds)
             .empty())
       return false;
   }
@@ -102,7 +103,7 @@
                         hasDeclaration(cxxConstructorDecl(isCopyConstructor())),
                         argumentCountIs(1),
                         hasArgument(0, AccessToFieldInParam)))))))),
-            *Ctor, *Context)
+            *Ctor, *Context, *Bounds)
             .empty())
       return false;
   }
@@ -116,6 +117,7 @@
 /// operator, has copy signature, returns a reference to "*this" and copies
 /// all its members and subobjects.
 static bool isCopyAssignmentAndCanBeDefaulted(ASTContext *Context,
+                                              ASTContext::Bounds *Bounds,
                                               const CXXMethodDecl *Operator) {
   const auto *Record = Operator->getParent();
   const auto *Param = Operator->getParamDecl(0);
@@ -132,7 +134,7 @@
   if (Compound->body_empty() ||
       match(returnStmt(has(ignoringParenImpCasts(unaryOperator(
                 hasOperatorName("*"), hasUnaryOperand(cxxThisExpr()))))),
-            *Compound->body_back(), *Context)
+            *Compound->body_back(), *Context, *Bounds)
           .empty())
     return false;
 
@@ -159,7 +161,7 @@
                   argumentCountIs(1),
                   hasArgument(0,
                               declRefExpr(to(varDecl(equalsNode(Param)))))))))),
-              *Compound, *Context)
+              *Compound, *Context, *Bounds)
             .empty())
       return false;
   }
@@ -179,7 +181,7 @@
                 cxxOperatorCallExpr(hasOverloadedOperatorName("="),
                                     argumentCountIs(2), hasArgument(0, LHS),
                                     hasArgument(1, RHS))))))),
-            *Compound, *Context)
+            *Compound, *Context, *Bounds)
             .empty())
       return false;
   }
@@ -277,7 +279,8 @@
     if (Ctor->getNumParams() == 0) {
       SpecialFunctionName = "default constructor";
     } else {
-      if (!isCopyConstructorAndCanBeDefaulted(Result.Context, Ctor))
+      if (!isCopyConstructorAndCanBeDefaulted(Result.Context, Result.Bounds,
+                                              Ctor))
         return;
       SpecialFunctionName = "copy constructor";
       // If there are constructor initializers, they must be removed.
@@ -289,7 +292,8 @@
   } else if (isa<CXXDestructorDecl>(SpecialFunctionDecl)) {
     SpecialFunctionName = "destructor";
   } else {
-    if (!isCopyAssignmentAndCanBeDefaulted(Result.Context, SpecialFunctionDecl))
+    if (!isCopyAssignmentAndCanBeDefaulted(Result.Context, Result.Bounds,
+                                           SpecialFunctionDecl))
       return;
     SpecialFunctionName = "copy-assignment operator";
   }
Index: clang-tidy/modernize/MakeSmartPtrCheck.h
===================================================================
--- clang-tidy/modernize/MakeSmartPtrCheck.h
+++ clang-tidy/modernize/MakeSmartPtrCheck.h
@@ -52,15 +52,15 @@
   const std::string MakeSmartPtrFunctionName;
   const bool IgnoreMacros;
 
-  void checkConstruct(SourceManager &SM, ASTContext *Ctx,
+  void checkConstruct(SourceManager &SM, ASTContext *, ASTContext::Bounds *,
                       const CXXConstructExpr *Construct, const QualType *Type,
                       const CXXNewExpr *New);
-  void checkReset(SourceManager &SM, ASTContext *Ctx,
+  void checkReset(SourceManager &SM, ASTContext *, ASTContext::Bounds *,
                   const CXXMemberCallExpr *Member, const CXXNewExpr *New);
 
   /// Returns true when the fixes for replacing CXXNewExpr are generated.
   bool replaceNew(DiagnosticBuilder &Diag, const CXXNewExpr *New,
-                  SourceManager &SM, ASTContext *Ctx);
+                  SourceManager &SM, ASTContext *, ASTContext::Bounds *);
   void insertHeader(DiagnosticBuilder &Diag, FileID FD);
 };
 
Index: clang-tidy/modernize/MakeSmartPtrCheck.cpp
===================================================================
--- clang-tidy/modernize/MakeSmartPtrCheck.cpp
+++ clang-tidy/modernize/MakeSmartPtrCheck.cpp
@@ -131,12 +131,13 @@
   if (New->isArray() && !New->hasInitializer())
     return;
   if (Construct)
-    checkConstruct(SM, Result.Context, Construct, Type, New);
+    checkConstruct(SM, Result.Context, Result.Bounds, Construct, Type, New);
   else if (Reset)
-    checkReset(SM, Result.Context, Reset, New);
+    checkReset(SM, Result.Context, Result.Bounds, Reset, New);
 }
 
 void MakeSmartPtrCheck::checkConstruct(SourceManager &SM, ASTContext *Ctx,
+                                       ASTContext::Bounds *Bounds,
                                        const CXXConstructExpr *Construct,
                                        const QualType *Type,
                                        const CXXNewExpr *New) {
@@ -163,7 +164,7 @@
     return;
   }
 
-  if (!replaceNew(Diag, New, SM, Ctx)) {
+  if (!replaceNew(Diag, New, SM, Ctx, Bounds)) {
     return;
   }
 
@@ -203,6 +204,7 @@
 }
 
 void MakeSmartPtrCheck::checkReset(SourceManager &SM, ASTContext *Ctx,
+                                   ASTContext::Bounds *Bounds,
                                    const CXXMemberCallExpr *Reset,
                                    const CXXNewExpr *New) {
   const auto *Expr = cast<MemberExpr>(Reset->getCallee());
@@ -233,7 +235,7 @@
     return;
   }
 
-  if (!replaceNew(Diag, New, SM, Ctx)) {
+  if (!replaceNew(Diag, New, SM, Ctx, Bounds)) {
     return;
   }
 
@@ -251,11 +253,12 @@
 
 bool MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag,
                                    const CXXNewExpr *New, SourceManager &SM,
-                                   ASTContext *Ctx) {
+                                   ASTContext *Ctx,
+                                   ASTContext::Bounds *Bounds) {
   auto SkipParensParents = [&](const Expr *E) {
     for (const Expr *OldE = nullptr; E != OldE;) {
       OldE = E;
-      for (const auto &Node : Ctx->getParents(*E)) {
+      for (const auto &Node : Ctx->getParents(*E, *Bounds)) {
         if (const Expr *Parent = Node.get<ParenExpr>()) {
           E = Parent;
           break;
Index: clang-tidy/modernize/LoopConvertCheck.h
===================================================================
--- clang-tidy/modernize/LoopConvertCheck.h
+++ clang-tidy/modernize/LoopConvertCheck.h
@@ -36,16 +36,17 @@
 
   void getAliasRange(SourceManager &SM, SourceRange &DeclRange);
 
-  void doConversion(ASTContext *Context, const VarDecl *IndexVar,
-                    const ValueDecl *MaybeContainer, const UsageResult &Usages,
-                    const DeclStmt *AliasDecl, bool AliasUseRequired,
-                    bool AliasFromForInit, const ForStmt *Loop,
-                    RangeDescriptor Descriptor);
+  void doConversion(ASTContext *Context, ASTContext::Bounds *Bounds,
+                    const VarDecl *IndexVar, const ValueDecl *MaybeContainer,
+                    const UsageResult &Usages, const DeclStmt *AliasDecl,
+                    bool AliasUseRequired, bool AliasFromForInit,
+                    const ForStmt *Loop, RangeDescriptor Descriptor);
 
   StringRef getContainerString(ASTContext *Context, const ForStmt *Loop,
                                const Expr *ContainerExpr);
 
   void getArrayLoopQualifiers(ASTContext *Context,
+                              ASTContext::Bounds *Bounds,
                               const ast_matchers::BoundNodes &Nodes,
                               const Expr *ContainerExpr,
                               const UsageResult &Usages,
@@ -55,7 +56,7 @@
                                  const ast_matchers::BoundNodes &Nodes,
                                  RangeDescriptor &Descriptor);
 
-  void determineRangeDescriptor(ASTContext *Context,
+  void determineRangeDescriptor(ASTContext *Context, ASTContext::Bounds *Bounds,
                                 const ast_matchers::BoundNodes &Nodes,
                                 const ForStmt *Loop, LoopFixerKind FixerKind,
                                 const Expr *ContainerExpr,
Index: clang-tidy/modernize/LoopConvertCheck.cpp
===================================================================
--- clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tidy/modernize/LoopConvertCheck.cpp
@@ -386,10 +386,11 @@
 /// \brief Given an expression that represents an usage of an element from the
 /// containter that we are iterating over, returns false when it can be
 /// guaranteed this element cannot be modified as a result of this usage.
-static bool canBeModified(ASTContext *Context, const Expr *E) {
+static bool canBeModified(ASTContext *Context, ASTContext::Bounds *Bounds,
+                          const Expr *E) {
   if (E->getType().isConstQualified())
     return false;
-  auto Parents = Context->getParents(*E);
+  auto Parents = Context->getParents(*E, *Bounds);
   if (Parents.size() != 1)
     return true;
   if (const auto *Cast = Parents[0].get<ImplicitCastExpr>()) {
@@ -405,15 +406,16 @@
 
 /// \brief Returns true when it can be guaranteed that the elements of the
 /// container are not being modified.
-static bool usagesAreConst(ASTContext *Context, const UsageResult &Usages) {
+static bool usagesAreConst(ASTContext *Context, ASTContext::Bounds *Bounds,
+                           const UsageResult &Usages) {
   for (const Usage &U : Usages) {
     // Lambda captures are just redeclarations (VarDecl) of the same variable,
     // not expressions. If we want to know if a variable that is captured by
     // reference can be modified in an usage inside the lambda's body, we need
     // to find the expression corresponding to that particular usage, later in
     // this loop.
     if (U.Kind != Usage::UK_CaptureByCopy && U.Kind != Usage::UK_CaptureByRef &&
-        canBeModified(Context, U.Expression))
+        canBeModified(Context, Bounds, U.Expression))
       return false;
   }
   return true;
@@ -515,7 +517,7 @@
 /// \brief Computes the changes needed to convert a given for loop, and
 /// applies them.
 void LoopConvertCheck::doConversion(
-    ASTContext *Context, const VarDecl *IndexVar,
+    ASTContext *Context, ASTContext::Bounds *Bounds, const VarDecl *IndexVar,
     const ValueDecl *MaybeContainer, const UsageResult &Usages,
     const DeclStmt *AliasDecl, bool AliasUseRequired, bool AliasFromForInit,
     const ForStmt *Loop, RangeDescriptor Descriptor) {
@@ -576,7 +578,7 @@
         // the replacement it must be accessed through the '.' operator.
         ReplaceText = Usage.Kind == Usage::UK_MemberThroughArrow ? VarName + "."
                                                                  : VarName;
-        auto Parents = Context->getParents(*Usage.Expression);
+        auto Parents = Context->getParents(*Usage.Expression, *Bounds);
         if (Parents.size() == 1) {
           if (const auto *Paren = Parents[0].get<ParenExpr>()) {
             // Usage.Expression will be replaced with the new index variable,
@@ -666,13 +668,14 @@
 /// \brief Determines what kind of 'auto' must be used after converting a for
 /// loop that iterates over an array or pseudoarray.
 void LoopConvertCheck::getArrayLoopQualifiers(ASTContext *Context,
+                                              ASTContext::Bounds *Bounds,
                                               const BoundNodes &Nodes,
                                               const Expr *ContainerExpr,
                                               const UsageResult &Usages,
                                               RangeDescriptor &Descriptor) {
   // On arrays and pseudoarrays, we must figure out the qualifiers from the
   // usages.
-  if (usagesAreConst(Context, Usages) ||
+  if (usagesAreConst(Context, Bounds, Usages) ||
       containerIsConst(ContainerExpr, Descriptor.ContainerNeedsDereference)) {
     Descriptor.DerefByConstRef = true;
   }
@@ -742,15 +745,16 @@
 
 /// \brief Determines the parameters needed to build the range replacement.
 void LoopConvertCheck::determineRangeDescriptor(
-    ASTContext *Context, const BoundNodes &Nodes, const ForStmt *Loop,
-    LoopFixerKind FixerKind, const Expr *ContainerExpr,
+    ASTContext *Context, ASTContext::Bounds *Bounds, const BoundNodes &Nodes,
+    const ForStmt *Loop, LoopFixerKind FixerKind, const Expr *ContainerExpr,
     const UsageResult &Usages, RangeDescriptor &Descriptor) {
   Descriptor.ContainerString = getContainerString(Context, Loop, ContainerExpr);
 
   if (FixerKind == LFK_Iterator)
     getIteratorLoopQualifiers(Context, Nodes, Descriptor);
   else
-    getArrayLoopQualifiers(Context, Nodes, ContainerExpr, Usages, Descriptor);
+    getArrayLoopQualifiers(Context, Bounds, Nodes, ContainerExpr, Usages,
+                           Descriptor);
 }
 
 /// \brief Check some of the conditions that must be met for the loop to be
@@ -892,8 +896,8 @@
 
   // Find out which qualifiers we have to use in the loop range.
   const UsageResult &Usages = Finder.getUsages();
-  determineRangeDescriptor(Context, Nodes, Loop, FixerKind, ContainerExpr,
-                           Usages, Descriptor);
+  determineRangeDescriptor(Context, Result.Bounds, Nodes, Loop, FixerKind,
+                           ContainerExpr, Usages, Descriptor);
 
   // Ensure that we do not try to move an expression dependent on a local
   // variable declared inside the loop outside of it.
@@ -910,7 +914,8 @@
       ConfidenceLevel.getLevel() < MinConfidence)
     return;
 
-  doConversion(Context, LoopVar, getReferencedVariable(ContainerExpr), Usages,
+  doConversion(Context, Result.Bounds, LoopVar,
+               getReferencedVariable(ContainerExpr), Usages,
                Finder.getAliasDecl(), Finder.aliasUseRequired(),
                Finder.aliasFromForInit(), Loop, Descriptor);
 }
Index: clang-tidy/google/AvoidCStyleCastsCheck.cpp
===================================================================
--- clang-tidy/google/AvoidCStyleCastsCheck.cpp
+++ clang-tidy/google/AvoidCStyleCastsCheck.cpp
@@ -104,7 +104,8 @@
   if (!getLangOpts().CPlusPlus || getLangOpts().ObjC)
     return;
   // Ignore code inside extern "C" {} blocks.
-  if (!match(expr(hasAncestor(linkageSpecDecl())), *CastExpr, *Result.Context)
+  if (!match(expr(hasAncestor(linkageSpecDecl())), *CastExpr, *Result.Context,
+             *Result.Bounds)
            .empty())
     return;
   // Ignore code in .c files and headers included from them, even if they are
Index: clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h
===================================================================
--- clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h
+++ clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h
@@ -46,6 +46,7 @@
   // To fix: Write a data member initializer, or mention it in the member
   // initializer list.
   void checkMissingMemberInitializer(ASTContext &Context,
+                                     ASTContext::Bounds &Bounds,
                                      const CXXRecordDecl &ClassDecl,
                                      const CXXConstructorDecl *Ctor);
 
Index: clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
===================================================================
--- clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
+++ clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
@@ -46,13 +46,13 @@
 }
 
 void removeFieldsInitializedInBody(
-    const Stmt &Stmt, ASTContext &Context,
+    const Stmt &Stmt, ASTContext &Context, ASTContext::Bounds &Bounds,
     SmallPtrSetImpl<const FieldDecl *> &FieldDecls) {
   auto Matches =
       match(findAll(binaryOperator(
                 hasOperatorName("="),
                 hasLHS(memberExpr(member(fieldDecl().bind("fieldDecl")))))),
-            Stmt, Context);
+            Stmt, Context, Bounds);
   for (const auto &Match : Matches)
     FieldDecls.erase(Match.getNodeAs<FieldDecl>("fieldDecl"));
 }
@@ -300,13 +300,15 @@
     // Skip declarations delayed by late template parsing without a body.
     if (!Ctor->getBody())
       return;
-    checkMissingMemberInitializer(*Result.Context, *Ctor->getParent(), Ctor);
+    checkMissingMemberInitializer(*Result.Context, *Result.Bounds,
+                                  *Ctor->getParent(), Ctor);
     checkMissingBaseClassInitializer(*Result.Context, *Ctor->getParent(), Ctor);
   } else if (const auto *Record =
                  Result.Nodes.getNodeAs<CXXRecordDecl>("record")) {
     assert(Record->hasDefaultConstructor() &&
            "Matched record should have a default constructor");
-    checkMissingMemberInitializer(*Result.Context, *Record, nullptr);
+    checkMissingMemberInitializer(*Result.Context, *Result.Bounds, *Record,
+                                  nullptr);
     checkMissingBaseClassInitializer(*Result.Context, *Record, nullptr);
   } else if (const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var")) {
     checkUninitializedTrivialType(*Result.Context, Var);
@@ -340,8 +342,8 @@
 }
 
 void ProTypeMemberInitCheck::checkMissingMemberInitializer(
-    ASTContext &Context, const CXXRecordDecl &ClassDecl,
-    const CXXConstructorDecl *Ctor) {
+    ASTContext &Context, ASTContext::Bounds &Bounds,
+    const CXXRecordDecl &ClassDecl, const CXXConstructorDecl *Ctor) {
   bool IsUnion = ClassDecl.isUnion();
 
   if (IsUnion && ClassDecl.hasInClassInitializer())
@@ -369,7 +371,8 @@
         FieldsToInit.erase(Init->getAnyMember());
       }
     }
-    removeFieldsInitializedInBody(*Ctor->getBody(), Context, FieldsToInit);
+    removeFieldsInitializedInBody(*Ctor->getBody(), Context, Bounds,
+                                  FieldsToInit);
   }
 
   // Collect all fields in order, both direct fields and indirect fields from
Index: clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp
===================================================================
--- clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp
+++ clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp
@@ -37,7 +37,7 @@
   const Expr *E = &Node;
   do {
     ASTContext::DynTypedNodeList Parents =
-        Finder->getASTContext().getParents(*E);
+        Finder->getASTContext().getParents(*E, Finder->getASTBounds());
     if (Parents.size() != 1)
       return false;
     E = Parents[0].get<Expr>();
Index: clang-tidy/bugprone/UseAfterMoveCheck.cpp
===================================================================
--- clang-tidy/bugprone/UseAfterMoveCheck.cpp
+++ clang-tidy/bugprone/UseAfterMoveCheck.cpp
@@ -37,7 +37,8 @@
 /// various internal helper functions).
 class UseAfterMoveFinder {
 public:
-  UseAfterMoveFinder(ASTContext *TheContext);
+  UseAfterMoveFinder(ASTContext *Context, ASTContext::Bounds *Bounds)
+      : Context(Context), Bounds(Bounds) {}
 
   // Within the given function body, finds the first use of 'MovedVariable' that
   // occurs after 'MovingCall' (the expression that performs the move). If a
@@ -60,6 +61,7 @@
                   llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs);
 
   ASTContext *Context;
+  ASTContext::Bounds *Bounds;
   std::unique_ptr<ExprSequence> Sequence;
   std::unique_ptr<StmtToBlockMap> BlockMap;
   llvm::SmallPtrSet<const CFGBlock *, 8> Visited;
@@ -81,9 +83,6 @@
                    to(functionDecl(ast_matchers::isTemplateInstantiation())))));
 }
 
-UseAfterMoveFinder::UseAfterMoveFinder(ASTContext *TheContext)
-    : Context(TheContext) {}
-
 bool UseAfterMoveFinder::find(Stmt *FunctionBody, const Expr *MovingCall,
                               const ValueDecl *MovedVariable,
                               UseAfterMove *TheUseAfterMove) {
@@ -102,9 +101,9 @@
   if (!TheCFG)
     return false;
 
-  Sequence =
-      llvm::make_unique<ExprSequence>(TheCFG.get(), FunctionBody, Context);
-  BlockMap = llvm::make_unique<StmtToBlockMap>(TheCFG.get(), Context);
+  Sequence = llvm::make_unique<ExprSequence>(TheCFG.get(), FunctionBody,
+                                             Context, Bounds);
+  BlockMap = llvm::make_unique<StmtToBlockMap>(TheCFG.get(), Context, Bounds);
   Visited.clear();
 
   const CFGBlock *Block = BlockMap->blockContainingStmt(MovingCall);
@@ -254,14 +253,15 @@
                                       unless(inDecltypeOrTemplateArg()))
                               .bind("declref");
 
-    addDeclRefs(match(findAll(DeclRefMatcher), *S->getStmt(), *Context));
+    addDeclRefs(
+        match(findAll(DeclRefMatcher), *S->getStmt(), *Context, *Bounds));
     addDeclRefs(match(
         findAll(cxxOperatorCallExpr(anyOf(hasOverloadedOperatorName("*"),
                                           hasOverloadedOperatorName("->"),
                                           hasOverloadedOperatorName("[]")),
                                     hasArgument(0, DeclRefMatcher))
                     .bind("operator")),
-        *S->getStmt(), *Context));
+        *S->getStmt(), *Context, *Bounds));
   }
 }
 
@@ -335,7 +335,7 @@
       continue;
 
     SmallVector<BoundNodes, 1> Matches =
-        match(findAll(ReinitMatcher), *S->getStmt(), *Context);
+        match(findAll(ReinitMatcher), *S->getStmt(), *Context, *Bounds);
 
     for (const auto &Match : Matches) {
       const auto *TheStmt = Match.getNodeAs<Stmt>("reinit");
@@ -428,7 +428,7 @@
   if (!Arg->getDecl()->getDeclContext()->isFunctionOrMethod())
     return;
 
-  UseAfterMoveFinder finder(Result.Context);
+  UseAfterMoveFinder finder(Result.Context, Result.Bounds);
   UseAfterMove Use;
   if (finder.find(FunctionBody, MovingCall, Arg->getDecl(), &Use))
     emitDiagnostic(MovingCall, Arg, Use, this, Result.Context);
Index: clang-tidy/bugprone/UnusedRaiiCheck.cpp
===================================================================
--- clang-tidy/bugprone/UnusedRaiiCheck.cpp
+++ clang-tidy/bugprone/UnusedRaiiCheck.cpp
@@ -80,8 +80,8 @@
   // Otherwise just suggest adding a name. To find the place to insert the name
   // find the first TypeLoc in the children of E, which always points to the
   // written type.
-  auto Matches =
-      match(expr(hasDescendant(typeLoc().bind("t"))), *E, *Result.Context);
+  auto Matches = match(expr(hasDescendant(typeLoc().bind("t"))), *E,
+                       *Result.Context, *Result.Bounds);
   const auto *TL = selectFirst<TypeLoc>("t", Matches);
   D << FixItHint::CreateInsertion(
       Lexer::getLocForEndOfToken(TL->getEndLoc(), 0, *Result.SourceManager,
Index: clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp
===================================================================
--- clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp
+++ clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp
@@ -20,10 +20,11 @@
 namespace {
 
 bool isConcatenatedLiteralsOnPurpose(ASTContext *Ctx,
+                                     ASTContext::Bounds *Bounds,
                                      const StringLiteral *Lit) {
   // String literals surrounded by parentheses are assumed to be on purpose.
   //    i.e.:  const char* Array[] = { ("a" "b" "c"), "d", [...] };
-  auto Parents = Ctx->getParents(*Lit);
+  auto Parents = Ctx->getParents(*Lit, *Bounds);
   if (Parents.size() == 1 && Parents[0].get<ParenExpr>() != nullptr)
     return true;
 
@@ -63,7 +64,8 @@
               MaxConcatenatedTokens) {
   return Node.getNumConcatenated() > 1 &&
          Node.getNumConcatenated() < MaxConcatenatedTokens &&
-         !isConcatenatedLiteralsOnPurpose(&Finder->getASTContext(), &Node);
+         !isConcatenatedLiteralsOnPurpose(&Finder->getASTContext(),
+                                          &Finder->getASTBounds(), &Node);
 }
 
 } // namespace
Index: clang-tidy/bugprone/MultipleStatementMacroCheck.cpp
===================================================================
--- clang-tidy/bugprone/MultipleStatementMacroCheck.cpp
+++ clang-tidy/bugprone/MultipleStatementMacroCheck.cpp
@@ -23,7 +23,7 @@
 
 /// \brief Find the next statement after `S`.
 const Stmt *nextStmt(const MatchFinder::MatchResult &Result, const Stmt *S) {
-  auto Parents = Result.Context->getParents(*S);
+  auto Parents = Result.Context->getParents(*S, *Result.Bounds);
   if (Parents.empty())
     return nullptr;
   const auto *Parent = Parents[0].get<Stmt>();
Index: clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp
===================================================================
--- clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp
+++ clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp
@@ -48,18 +48,18 @@
   auto DeclRef = ignoringParenImpCasts(declRefExpr(to(equalsNode(D))));
   if (!match(findAll(
                  unaryOperator(hasOperatorName("*"), hasUnaryOperand(DeclRef))),
-             *If, *Result.Context)
+             *If, *Result.Context, *Result.Bounds)
            .empty() ||
       !match(findAll(arraySubscriptExpr(hasBase(DeclRef))), *If,
-             *Result.Context)
+             *Result.Context, *Result.Bounds)
            .empty() ||
       // FIXME: We should still warn if the paremater is implicitly converted to
       // bool.
       !match(findAll(callExpr(hasAnyArgument(ignoringParenImpCasts(DeclRef)))),
-             *If, *Result.Context)
+             *If, *Result.Context, *Result.Bounds)
            .empty() ||
       !match(findAll(cxxDeleteExpr(has(ignoringParenImpCasts(expr(DeclRef))))),
-             *If, *Result.Context)
+             *If, *Result.Context, *Result.Bounds)
            .empty())
     return;
 
Index: clang-tidy/abseil/RedundantStrcatCallsCheck.cpp
===================================================================
--- clang-tidy/abseil/RedundantStrcatCallsCheck.cpp
+++ clang-tidy/abseil/RedundantStrcatCallsCheck.cpp
@@ -67,12 +67,12 @@
   static const auto* const Strcat = new auto(hasName("::absl::StrCat"));
   const auto IsStrcat = cxxBindTemporaryExpr(
       has(callExpr(callee(functionDecl(*Strcat))).bind("StrCat")));
-  if (const auto* SubStrcatCall = selectFirst<const CallExpr>(
+  if (const auto *SubStrcatCall = selectFirst<const CallExpr>(
           "StrCat",
-          match(stmt(anyOf(
-                    cxxConstructExpr(IsAlphanum, hasArgument(0, IsStrcat)),
-                    IsStrcat)),
-                *Arg->IgnoreParenImpCasts(), *Result.Context))) {
+          match(
+              stmt(anyOf(cxxConstructExpr(IsAlphanum, hasArgument(0, IsStrcat)),
+                         IsStrcat)),
+              *Arg->IgnoreParenImpCasts(), *Result.Context, *Result.Bounds))) {
     RemoveCallLeaveArgs(SubStrcatCall, CheckResult);
     return SubStrcatCall;
   }
Index: clang-reorder-fields/ReorderFieldsAction.cpp
===================================================================
--- clang-reorder-fields/ReorderFieldsAction.cpp
+++ clang-reorder-fields/ReorderFieldsAction.cpp
@@ -38,7 +38,7 @@
                                         ASTContext &Context) {
   auto Results =
       match(recordDecl(hasName(RecordName), isDefinition()).bind("recordDecl"),
-            Context);
+            Context, Context.fullBounds());
   if (Results.empty()) {
     llvm::errs() << "Definition of " << RecordName << "  not found\n";
     return nullptr;
@@ -107,7 +107,7 @@
   // object expression
   auto FoundExprs =
       match(findAll(memberExpr(hasObjectExpression(cxxThisExpr())).bind("ME")),
-            *Initializer->getInit(), Context);
+            *Initializer->getInit(), Context, Context.fullBounds());
   for (BoundNodes &BN : FoundExprs)
     if (auto *MemExpr = BN.getNodeAs<MemberExpr>("ME"))
       if (auto *FD = dyn_cast<FieldDecl>(MemExpr->getMemberDecl()))
@@ -291,7 +291,7 @@
     if (!CXXRD || CXXRD->isAggregate())
       for (auto Result :
            match(initListExpr(hasType(equalsNode(RD))).bind("initListExpr"),
-                 Context))
+                 Context, Context.fullBounds()))
         if (!reorderFieldsInInitListExpr(
                 Result.getNodeAs<InitListExpr>("initListExpr"), NewFieldsOrder,
                 Context, Replacements)) {
Index: clang-query/Query.cpp
===================================================================
--- clang-query/Query.cpp
+++ clang-query/Query.cpp
@@ -98,7 +98,7 @@
       OS << "Not a valid top-level matcher.\n";
       return false;
     }
-    Finder.matchAST(AST->getASTContext());
+    Finder.matchAST(AST->getASTContext(), AST->getASTContext().fullBounds());
 
     if (QS.PrintMatcher) {
       std::string prefixText = "Matcher: ";
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to