r310853 - [rename] Introduce symbol occurrences

Alex L via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 14 09:21:01 PDT 2017


It's an NFC, thus untested.

On 14 August 2017 at 17:19, Alex Lorenz via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> Author: arphaman
> Date: Mon Aug 14 09:19:24 2017
> New Revision: 310853
>
> URL: http://llvm.org/viewvc/llvm-project?rev=310853&view=rev
> Log:
> [rename] Introduce symbol occurrences
>
> Symbol occurrences store the results of local rename and will also be used
> for
> the global, indexed rename results. Their kind is used to determine
> whether they
> should be renamed automatically or not. They can be converted to a set of
> AtomicChanges as well.
>
> Differential Revision: https://reviews.llvm.org/D36156
>
> Added:
>     cfe/trunk/include/clang/Tooling/Refactoring/Rename/SymbolName.h
>     cfe/trunk/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h
>     cfe/trunk/lib/Tooling/Refactoring/Rename/SymbolOccurrences.cpp
> Modified:
>     cfe/trunk/include/clang/Tooling/Refactoring/Rename/RenamingAction.h
>     cfe/trunk/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h
>     cfe/trunk/lib/Tooling/Refactoring/CMakeLists.txt
>     cfe/trunk/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
>     cfe/trunk/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
>
> Modified: cfe/trunk/include/clang/Tooling/Refactoring/Rename/
> RenamingAction.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Tooling/Refactoring/Rename/RenamingAction.h?rev=
> 310853&r1=310852&r2=310853&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Tooling/Refactoring/Rename/RenamingAction.h
> (original)
> +++ cfe/trunk/include/clang/Tooling/Refactoring/Rename/RenamingAction.h
> Mon Aug 14 09:19:24 2017
> @@ -16,6 +16,9 @@
>  #define LLVM_CLANG_TOOLING_REFACTOR_RENAME_RENAMING_ACTION_H
>
>  #include "clang/Tooling/Refactoring.h"
> +#include "clang/Tooling/Refactoring/AtomicChange.h"
> +#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h"
> +#include "llvm/Support/Error.h"
>
>  namespace clang {
>  class ASTConsumer;
> @@ -42,6 +45,13 @@ private:
>    bool PrintLocations;
>  };
>
> +/// Returns source replacements that correspond to the rename of the given
> +/// symbol occurrences.
> +llvm::Expected<std::vector<AtomicChange>>
> +createRenameReplacements(const SymbolOccurrences &Occurrences,
> +                         const SourceManager &SM,
> +                         ArrayRef<StringRef> NewNameStrings);
> +
>  /// Rename all symbols identified by the given USRs.
>  class QualifiedRenamingAction {
>  public:
>
> Added: cfe/trunk/include/clang/Tooling/Refactoring/Rename/SymbolName.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Tooling/Refactoring/Rename/SymbolName.h?rev=310853&view=auto
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Tooling/Refactoring/Rename/SymbolName.h
> (added)
> +++ cfe/trunk/include/clang/Tooling/Refactoring/Rename/SymbolName.h Mon
> Aug 14 09:19:24 2017
> @@ -0,0 +1,49 @@
> +//===--- SymbolName.h - Clang refactoring library
> -------------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===------------------------------------------------------
> ----------------===//
> +
> +#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_NAME_H
> +#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_NAME_H
> +
> +#include "clang/Basic/LLVM.h"
> +#include "llvm/ADT/ArrayRef.h"
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/ADT/StringRef.h"
> +
> +namespace clang {
> +namespace tooling {
> +
> +/// A name of a symbol.
> +///
> +/// Symbol's name can be composed of multiple strings. For example,
> Objective-C
> +/// methods can contain multiple argument lables:
> +///
> +/// \code
> +/// - (void) myMethodNamePiece: (int)x anotherNamePieces:(int)y;
> +/// //       ^~ string 0 ~~~~~         ^~ string 1 ~~~~~
> +/// \endcode
> +class SymbolName {
> +public:
> +  SymbolName(StringRef Name) {
> +    // While empty symbol names are valid (Objective-C selectors can have
> empty
> +    // name pieces), occurrences Objective-C selectors are created using
> an
> +    // array of strings instead of just one string.
> +    assert(!Name.empty() && "Invalid symbol name!");
> +    this->Name.push_back(Name.str());
> +  }
> +
> +  ArrayRef<std::string> getNamePieces() const { return Name; }
> +
> +private:
> +  llvm::SmallVector<std::string, 1> Name;
> +};
> +
> +} // end namespace tooling
> +} // end namespace clang
> +
> +#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_NAME_H
>
> Added: cfe/trunk/include/clang/Tooling/Refactoring/Rename/
> SymbolOccurrences.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Tooling/Refactoring/Rename/SymbolOccurrences.h?rev=310853&view=auto
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h
> (added)
> +++ cfe/trunk/include/clang/Tooling/Refactoring/Rename/SymbolOccurrences.h
> Mon Aug 14 09:19:24 2017
> @@ -0,0 +1,91 @@
> +//===--- SymbolOccurrences.h - Clang refactoring library
> ------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===------------------------------------------------------
> ----------------===//
> +
> +#ifndef LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_OCCURRENCES_H
> +#define LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_OCCURRENCES_H
> +
> +#include "clang/Basic/LLVM.h"
> +#include "clang/Basic/SourceLocation.h"
> +#include "llvm/ADT/ArrayRef.h"
> +#include "llvm/ADT/StringRef.h"
> +#include <vector>
> +
> +namespace clang {
> +namespace tooling {
> +
> +class SymbolName;
> +
> +/// An occurrence of a symbol in the source.
> +///
> +/// Occurrences can have difference kinds, that describe whether this
> occurrence
> +/// is an exact semantic match, or whether this is a weaker textual match
> that's
> +/// not guaranteed to represent the exact declaration.
> +///
> +/// A single occurrence of a symbol can span more than one source range.
> For
> +/// example, Objective-C selectors can contain multiple argument labels:
> +///
> +/// \code
> +/// [object selectorPiece1: ... selectorPiece2: ...];
> +/// //      ^~~ range 0 ~~      ^~~ range 1 ~~
> +/// \endcode
> +///
> +/// We have to replace the text in both range 0 and range 1 when renaming
> the
> +/// Objective-C method 'selectorPiece1:selectorPiece2'.
> +class SymbolOccurrence {
> +public:
> +  enum OccurrenceKind {
> +    /// This occurrence is an exact match and can be renamed
> automatically.
> +    ///
> +    /// Note:
> +    /// Symbol occurrences in macro arguments that expand to different
> +    /// declarations get marked as exact matches, and thus the renaming
> engine
> +    /// will rename them e.g.:
> +    ///
> +    /// \code
> +    ///   #define MACRO(x) x + ns::x
> +    ///   int foo(int var) {
> +    ///     return MACRO(var); // var is renamed automatically here when
> +    ///                        // either var or ns::var is renamed.
> +    ///   };
> +    /// \endcode
> +    ///
> +    /// The user will have to fix their code manually after performing
> such a
> +    /// rename.
> +    /// FIXME: The rename verifier should notify user about this issue.
> +    MatchingSymbol
> +  };
> +
> +  SymbolOccurrence(const SymbolName &Name, OccurrenceKind Kind,
> +                   ArrayRef<SourceLocation> Locations);
> +
> +  SymbolOccurrence(SymbolOccurrence &&) = default;
> +  SymbolOccurrence &operator=(SymbolOccurrence &&) = default;
> +
> +  OccurrenceKind getKind() const { return Kind; }
> +
> +  ArrayRef<SourceRange> getNameRanges() const {
> +    if (MultipleRanges) {
> +      return llvm::makeArrayRef(MultipleRanges.get(),
> +                                RangeOrNumRanges.getBegin().
> getRawEncoding());
> +    }
> +    return RangeOrNumRanges;
> +  }
> +
> +private:
> +  OccurrenceKind Kind;
> +  std::unique_ptr<SourceRange[]> MultipleRanges;
> +  SourceRange RangeOrNumRanges;
> +};
> +
> +using SymbolOccurrences = std::vector<SymbolOccurrence>;
> +
> +} // end namespace tooling
> +} // end namespace clang
> +
> +#endif // LLVM_CLANG_TOOLING_REFACTOR_RENAME_SYMBOL_OCCURRENCES_H
>
> Modified: cfe/trunk/include/clang/Tooling/Refactoring/Rename/
> USRLocFinder.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/
> clang/Tooling/Refactoring/Rename/USRLocFinder.h?rev=
> 310853&r1=310852&r2=310853&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h
> (original)
> +++ cfe/trunk/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h Mon
> Aug 14 09:19:24 2017
> @@ -19,6 +19,7 @@
>  #include "clang/AST/AST.h"
>  #include "clang/Tooling/Core/Replacement.h"
>  #include "clang/Tooling/Refactoring/AtomicChange.h"
> +#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h"
>  #include "llvm/ADT/StringRef.h"
>  #include <string>
>  #include <vector>
> @@ -38,10 +39,13 @@ std::vector<tooling::AtomicChange>
>  createRenameAtomicChanges(llvm::ArrayRef<std::string> USRs,
>                            llvm::StringRef NewName, Decl
> *TranslationUnitDecl);
>
> -// FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree!
> -std::vector<SourceLocation>
> -getLocationsOfUSRs(const std::vector<std::string> &USRs,
> -                   llvm::StringRef PrevName, Decl *Decl);
> +/// Finds the symbol occurrences for the symbol that's identified by the
> given
> +/// USR set.
> +///
> +/// \return SymbolOccurrences that can be converted to AtomicChanges when
> +/// renaming.
> +SymbolOccurrences getOccurrencesOfUSRs(ArrayRef<std::string> USRs,
> +                                       StringRef PrevName, Decl *Decl);
>
>  } // end namespace tooling
>  } // end namespace clang
>
> Modified: cfe/trunk/lib/Tooling/Refactoring/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/
> Refactoring/CMakeLists.txt?rev=310853&r1=310852&r2=310853&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Tooling/Refactoring/CMakeLists.txt (original)
> +++ cfe/trunk/lib/Tooling/Refactoring/CMakeLists.txt Mon Aug 14 09:19:24
> 2017
> @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS Support)
>  add_clang_library(clangToolingRefactor
>    AtomicChange.cpp
>    Rename/RenamingAction.cpp
> +  Rename/SymbolOccurrences.cpp
>    Rename/USRFinder.cpp
>    Rename/USRFindingAction.cpp
>    Rename/USRLocFinder.cpp
>
> Modified: cfe/trunk/lib/Tooling/Refactoring/Rename/RenamingAction.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/
> Refactoring/Rename/RenamingAction.cpp?rev=310853&
> r1=310852&r2=310853&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Tooling/Refactoring/Rename/RenamingAction.cpp (original)
> +++ cfe/trunk/lib/Tooling/Refactoring/Rename/RenamingAction.cpp Mon Aug
> 14 09:19:24 2017
> @@ -24,6 +24,7 @@
>  #include "clang/Tooling/Refactoring.h"
>  #include "clang/Tooling/Refactoring/Rename/USRLocFinder.h"
>  #include "clang/Tooling/Tooling.h"
> +#include "llvm/ADT/STLExtras.h"
>  #include <string>
>  #include <vector>
>
> @@ -32,6 +33,45 @@ using namespace llvm;
>  namespace clang {
>  namespace tooling {
>
> +Expected<std::vector<AtomicChange>>
> +createRenameReplacements(const SymbolOccurrences &Occurrences,
> +                         const SourceManager &SM,
> +                         ArrayRef<StringRef> NewNameStrings) {
> +  // FIXME: A true local rename can use just one AtomicChange.
> +  std::vector<AtomicChange> Changes;
> +  for (const auto &Occurrence : Occurrences) {
> +    ArrayRef<SourceRange> Ranges = Occurrence.getNameRanges();
> +    assert(NewNameStrings.size() == Ranges.size() &&
> +           "Mismatching number of ranges and name pieces");
> +    AtomicChange Change(SM, Ranges[0].getBegin());
> +    for (const auto &Range : llvm::enumerate(Ranges)) {
> +      auto Error =
> +          Change.replace(SM, CharSourceRange::getCharRange(
> Range.value()),
> +                         NewNameStrings[Range.index()]);
> +      if (Error)
> +        return std::move(Error);
> +    }
> +    Changes.push_back(std::move(Change));
> +  }
> +  return Changes;
> +}
> +
> +/// Takes each atomic change and inserts its replacements into the set of
> +/// replacements that belong to the appropriate file.
> +static void convertChangesToFileReplacements(
> +    ArrayRef<AtomicChange> AtomicChanges,
> +    std::map<std::string, tooling::Replacements> *FileToReplaces) {
> +  for (const auto &AtomicChange : AtomicChanges) {
> +    for (const auto &Replace : AtomicChange.getReplacements()) {
> +      llvm::Error Err = (*FileToReplaces)[Replace.
> getFilePath()].add(Replace);
> +      if (Err) {
> +        llvm::errs() << "Renaming failed in " << Replace.getFilePath() <<
> "! "
> +                     << llvm::toString(std::move(Err)) << "\n";
> +      }
> +    }
> +  }
> +}
> +
>  class RenamingASTConsumer : public ASTConsumer {
>  public:
>    RenamingASTConsumer(
> @@ -52,29 +92,29 @@ public:
>                         const std::string &PrevName,
>                         const std::vector<std::string> &USRs) {
>      const SourceManager &SourceMgr = Context.getSourceManager();
> -    std::vector<SourceLocation> RenamingCandidates;
> -    std::vector<SourceLocation> NewCandidates;
>
> -    NewCandidates = tooling::getLocationsOfUSRs(
> +    SymbolOccurrences Occurrences = tooling::getOccurrencesOfUSRs(
>          USRs, PrevName, Context.getTranslationUnitDecl());
> -    RenamingCandidates.insert(RenamingCandidates.end(),
> NewCandidates.begin(),
> -                              NewCandidates.end());
> -
> -    unsigned PrevNameLen = PrevName.length();
> -    for (const auto &Loc : RenamingCandidates) {
> -      if (PrintLocations) {
> -        FullSourceLoc FullLoc(Loc, SourceMgr);
> -        errs() << "clang-rename: renamed at: " <<
> SourceMgr.getFilename(Loc)
> +    if (PrintLocations) {
> +      for (const auto &Occurrence : Occurrences) {
> +        FullSourceLoc FullLoc(Occurrence.getNameRanges()[0].getBegin(),
> +                              SourceMgr);
> +        errs() << "clang-rename: renamed at: " <<
> SourceMgr.getFilename(FullLoc)
>                 << ":" << FullLoc.getSpellingLineNumber() << ":"
>                 << FullLoc.getSpellingColumnNumber() << "\n";
>        }
> -      // FIXME: better error handling.
> -      tooling::Replacement Replace(SourceMgr, Loc, PrevNameLen, NewName);
> -      llvm::Error Err = FileToReplaces[Replace.
> getFilePath()].add(Replace);
> -      if (Err)
> -        llvm::errs() << "Renaming failed in " << Replace.getFilePath() <<
> "! "
> -                     << llvm::toString(std::move(Err)) << "\n";
>      }
> +    // FIXME: Support multi-piece names.
> +    // FIXME: better error handling (propagate error out).
> +    StringRef NewNameRef = NewName;
> +    Expected<std::vector<AtomicChange>> Change =
> +        createRenameReplacements(Occurrences, SourceMgr, NewNameRef);
> +    if (!Change) {
> +      llvm::errs() << "Failed to create renaming replacements for '" <<
> PrevName
> +                   << "'! " << llvm::toString(Change.takeError()) <<
> "\n";
> +      return;
> +    }
> +    convertChangesToFileReplacements(*Change, &FileToReplaces);
>    }
>
>  private:
> @@ -103,15 +143,7 @@ public:
>        // ready.
>        auto AtomicChanges = tooling::createRenameAtomicChanges(
>            USRList[I], NewNames[I], Context.getTranslationUnitDecl());
> -      for (const auto AtomicChange : AtomicChanges) {
> -        for (const auto &Replace : AtomicChange.getReplacements()) {
> -          llvm::Error Err = FileToReplaces[Replace.
> getFilePath()].add(Replace);
> -          if (Err) {
> -            llvm::errs() << "Renaming failed in " << Replace.getFilePath()
> -                         << "! " << llvm::toString(std::move(Err)) <<
> "\n";
> -          }
> -        }
> -      }
> +      convertChangesToFileReplacements(AtomicChanges, &FileToReplaces);
>      }
>    }
>
>
> Added: cfe/trunk/lib/Tooling/Refactoring/Rename/SymbolOccurrences.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/
> Refactoring/Rename/SymbolOccurrences.cpp?rev=310853&view=auto
> ============================================================
> ==================
> --- cfe/trunk/lib/Tooling/Refactoring/Rename/SymbolOccurrences.cpp (added)
> +++ cfe/trunk/lib/Tooling/Refactoring/Rename/SymbolOccurrences.cpp Mon
> Aug 14 09:19:24 2017
> @@ -0,0 +1,37 @@
> +//===--- SymbolOccurrences.cpp - Clang refactoring library
> ----------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===------------------------------------------------------
> ----------------===//
> +
> +#include "clang/Tooling/Refactoring/Rename/SymbolOccurrences.h"
> +#include "clang/Tooling/Refactoring/Rename/SymbolName.h"
> +#include "llvm/ADT/STLExtras.h"
> +
> +using namespace clang;
> +using namespace tooling;
> +
> +SymbolOccurrence::SymbolOccurrence(const SymbolName &Name,
> OccurrenceKind Kind,
> +                                   ArrayRef<SourceLocation> Locations)
> +    : Kind(Kind) {
> +  ArrayRef<std::string> NamePieces = Name.getNamePieces();
> +  assert(Locations.size() == NamePieces.size() &&
> +         "mismatching number of locations and lengths");
> +  assert(!Locations.empty() && "no locations");
> +  if (Locations.size() == 1) {
> +    RangeOrNumRanges = SourceRange(
> +        Locations[0], Locations[0].getLocWithOffset(
> NamePieces[0].size()));
> +    return;
> +  }
> +  MultipleRanges = llvm::make_unique<SourceRange[]>(Locations.size());
> +  RangeOrNumRanges.setBegin(
> +      SourceLocation::getFromRawEncoding(Locations.size()));
> +  for (const auto &Loc : llvm::enumerate(Locations)) {
> +    MultipleRanges[Loc.index()] = SourceRange(
> +        Loc.value(),
> +        Loc.value().getLocWithOffset(NamePieces[Loc.index()].size()));
> +  }
> +}
>
> Modified: cfe/trunk/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/
> Refactoring/Rename/USRLocFinder.cpp?rev=310853&
> r1=310852&r2=310853&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp (original)
> +++ cfe/trunk/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp Mon Aug 14
> 09:19:24 2017
> @@ -23,6 +23,7 @@
>  #include "clang/Lex/Lexer.h"
>  #include "clang/Tooling/Core/Lookup.h"
>  #include "clang/Tooling/Refactoring/RecursiveSymbolVisitor.h"
> +#include "clang/Tooling/Refactoring/Rename/SymbolName.h"
>  #include "clang/Tooling/Refactoring/Rename/USRFinder.h"
>  #include "llvm/ADT/StringRef.h"
>  #include "llvm/Support/Casting.h"
> @@ -68,11 +69,9 @@ public:
>
>    // Non-visitors:
>
> -  // \brief Returns a list of unique locations. Duplicate or overlapping
> -  // locations are erroneous and should be reported!
> -  const std::vector<clang::SourceLocation> &getLocationsFound() const {
> -    return LocationsFound;
> -  }
> +  /// \brief Returns a set of unique symbol occurrences. Duplicate or
> +  /// overlapping occurrences are erroneous and should be reported!
> +  SymbolOccurrences takeOccurrences() { return std::move(Occurrences); }
>
>  private:
>    void checkAndAddLocation(SourceLocation Loc) {
> @@ -82,17 +81,18 @@ private:
>      StringRef TokenName =
>          Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc,
> EndLoc),
>                               Context.getSourceManager(),
> Context.getLangOpts());
> -    size_t Offset = TokenName.find(PrevName);
> +    size_t Offset = TokenName.find(PrevName.getNamePieces()[0]);
>
>      // The token of the source location we find actually has the old
>      // name.
>      if (Offset != StringRef::npos)
> -      LocationsFound.push_back(BeginLoc.getLocWithOffset(Offset));
> +      Occurrences.emplace_back(PrevName, SymbolOccurrence::
> MatchingSymbol,
> +                               BeginLoc.getLocWithOffset(Offset));
>    }
>
>    const std::set<std::string> USRSet;
> -  const std::string PrevName;
> -  std::vector<clang::SourceLocation> LocationsFound;
> +  const SymbolName PrevName;
> +  SymbolOccurrences Occurrences;
>    const ASTContext &Context;
>  };
>
> @@ -391,12 +391,11 @@ private:
>
>  } // namespace
>
> -std::vector<SourceLocation>
> -getLocationsOfUSRs(const std::vector<std::string> &USRs, StringRef
> PrevName,
> -                   Decl *Decl) {
> +SymbolOccurrences getOccurrencesOfUSRs(ArrayRef<std::string> USRs,
> +                                       StringRef PrevName, Decl *Decl) {
>    USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext());
>    Visitor.TraverseDecl(Decl);
> -  return Visitor.getLocationsFound();
> +  return Visitor.takeOccurrences();
>  }
>
>  std::vector<tooling::AtomicChange>
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170814/430b4434/attachment-0001.html>


More information about the cfe-commits mailing list