17 #include "llvm/ADT/PriorityQueue.h" 21 #include <unordered_set> 24 using namespace clang;
34 Mapping(Mapping &&Other) =
default;
35 Mapping &operator=(Mapping &&Other) =
default;
37 Mapping(
size_t Size) {
38 SrcToDst = std::make_unique<NodeId[]>(Size);
39 DstToSrc = std::make_unique<NodeId[]>(Size);
42 void link(NodeId Src, NodeId Dst) {
43 SrcToDst[Src] = Dst, DstToSrc[Dst] = Src;
46 NodeId getDst(NodeId Src)
const {
return SrcToDst[Src]; }
47 NodeId getSrc(NodeId Dst)
const {
return DstToSrc[Dst]; }
48 bool hasSrc(NodeId Src)
const {
return getDst(Src).isValid(); }
49 bool hasDst(NodeId Dst)
const {
return getSrc(Dst).isValid(); }
52 std::unique_ptr<NodeId[]> SrcToDst, DstToSrc;
65 void computeMapping();
68 void computeChangeKinds(Mapping &M);
73 return TheMapping.getDst(Id);
74 assert(&*Tree == &T2 &&
"Invalid tree.");
75 return TheMapping.getSrc(Id);
86 bool haveSameParents(
const Mapping &M,
NodeId Id1,
NodeId Id2)
const;
90 void addOptimalMapping(Mapping &M,
NodeId Id1,
NodeId Id2)
const;
94 double getJaccardSimilarity(
const Mapping &M,
NodeId Id1,
NodeId Id2)
const;
97 NodeId findCandidate(
const Mapping &M,
NodeId Id1)
const;
100 Mapping matchTopDown()
const;
103 void matchBottomUp(Mapping &M)
const;
119 typename std::enable_if<std::is_base_of<Stmt, T>::value, T>::
type *
Node,
121 :
Impl(Parent, dyn_cast<
Stmt>(Node), AST) {}
124 typename std::enable_if<std::is_base_of<Decl, T>::value, T>::
type *
Node,
126 :
Impl(Parent, dyn_cast<
Decl>(Node), AST) {}
147 int getNumberOfDescendants(
NodeId Id)
const;
149 int findPositionInParent(
NodeId Id,
bool Shifted =
false)
const;
151 std::string getRelativeName(
const NamedDecl *ND,
153 std::string getRelativeName(
const NamedDecl *ND)
const;
155 std::string getNodeValue(
NodeId Id)
const;
156 std::string getNodeValue(
const Node &
Node)
const;
157 std::string getDeclValue(
const Decl *D)
const;
158 std::string getStmtValue(
const Stmt *S)
const;
162 void setLeftMostDescendants();
194 PreorderVisitor(SyntaxTree::Impl &Tree) : Tree(Tree) {}
196 template <
class T> std::tuple<NodeId, NodeId> PreTraverse(T *ASTNode) {
198 Tree.Nodes.emplace_back();
199 Node &N = Tree.getMutableNode(MyId);
203 assert(!N.ASTNode.getNodeKind().isNone() &&
204 "Expected nodes to have a valid kind.");
205 if (Parent.isValid()) {
206 Node &
P = Tree.getMutableNode(Parent);
207 P.Children.push_back(MyId);
212 return std::make_tuple(MyId, Tree.getNode(MyId).Parent);
214 void PostTraverse(std::tuple<NodeId, NodeId>
State) {
215 NodeId MyId, PreviousParent;
216 std::tie(MyId, PreviousParent) =
State;
217 assert(MyId.isValid() &&
"Expecting to only traverse valid nodes.");
218 Parent = PreviousParent;
220 Node &N = Tree.getMutableNode(MyId);
221 N.RightMostDescendant = Id - 1;
222 assert(N.RightMostDescendant >= 0 &&
223 N.RightMostDescendant < Tree.getSize() &&
224 "Rightmost descendant must be a valid tree node.");
226 Tree.Leaves.push_back(MyId);
228 for (NodeId Child : N.Children)
229 N.Height =
std::max(N.Height, 1 + Tree.getNode(Child).Height);
231 bool TraverseDecl(
Decl *D) {
234 auto SavedState = PreTraverse(D);
236 PostTraverse(SavedState);
239 bool TraverseStmt(
Stmt *S) {
240 if (
auto *E = dyn_cast_or_null<Expr>(S))
241 S = E->IgnoreImplicit();
244 auto SavedState = PreTraverse(S);
246 PostTraverse(SavedState);
249 bool TraverseType(
QualType T) {
return true; }
253 auto SavedState = PreTraverse(Init);
255 PostTraverse(SavedState);
262 : Parent(Parent), AST(AST), TypePP(AST.getLangOpts()) {
267 :
Impl(Parent, AST) {
268 PreorderVisitor PreorderWalker(*
this);
269 PreorderWalker.TraverseDecl(N);
274 :
Impl(Parent, AST) {
275 PreorderVisitor PreorderWalker(*
this);
276 PreorderWalker.TraverseStmt(N);
282 std::vector<NodeId> Postorder;
283 std::function<void(NodeId)> Traverse = [&](
NodeId Id) {
287 Postorder.push_back(
Id);
295 std::vector<NodeId> Ids;
298 while (Expanded < Ids.size())
300 Ids.push_back(Child);
304 void SyntaxTree::Impl::initTree() {
305 setLeftMostDescendants();
308 std::function<void(NodeId)> PostorderTraverse = [&](
NodeId Id) {
310 PostorderTraverse(Child);
318 void SyntaxTree::Impl::setLeftMostDescendants() {
322 while ((Parent =
getNode(Cur).Parent).isValid() &&
323 getNode(Parent).Children[0] == Cur) {
344 for (
size_t I = 0, E = Siblings.size(); I < E; ++I) {
347 if (Siblings[I] == Id) {
352 llvm_unreachable(
"Node not found in parent's children.");
361 std::string ContextPrefix;
364 if (
auto *Namespace = dyn_cast<NamespaceDecl>(Context))
365 ContextPrefix = Namespace->getQualifiedNameAsString();
366 else if (
auto *Record = dyn_cast<RecordDecl>(Context))
367 ContextPrefix = Record->getQualifiedNameAsString();
369 if (
auto *Tag = dyn_cast<TagDecl>(Context))
370 ContextPrefix = Tag->getQualifiedNameAsString();
374 if (!ContextPrefix.empty() && StringRef(Val).startswith(ContextPrefix))
375 Val = Val.substr(ContextPrefix.size() + 1);
389 const auto &
P = Parents[0];
390 if (
const auto *D =
P.get<
Decl>())
391 return D->getDeclContext();
405 llvm_unreachable(
"Unknown initializer type");
420 llvm_unreachable(
"Fatal: unhandled AST node.\n");
425 if (
auto *
V = dyn_cast<ValueDecl>(D))
427 if (
auto *N = dyn_cast<NamedDecl>(D))
429 if (
auto *T = dyn_cast<TypedefNameDecl>(D))
430 return Value + T->getUnderlyingType().getAsString(
TypePP) +
";";
431 if (
auto *T = dyn_cast<TypeDecl>(D))
432 if (T->getTypeForDecl())
434 T->getTypeForDecl()->getCanonicalTypeInternal().getAsString(
TypePP) +
436 if (
auto *U = dyn_cast<UsingDirectiveDecl>(D))
437 return U->getNominatedNamespace()->getName();
438 if (
auto *A = dyn_cast<AccessSpecDecl>(D)) {
447 if (
auto *U = dyn_cast<UnaryOperator>(S))
449 if (
auto *B = dyn_cast<BinaryOperator>(S))
450 return B->getOpcodeStr();
451 if (
auto *M = dyn_cast<MemberExpr>(S))
453 if (
auto *I = dyn_cast<IntegerLiteral>(S)) {
455 I->getValue().toString(Str, 10,
false);
458 if (
auto *F = dyn_cast<FloatingLiteral>(S)) {
460 F->getValue().toString(Str);
463 if (
auto *D = dyn_cast<DeclRefExpr>(S))
465 if (
auto *String = dyn_cast<StringLiteral>(S))
466 return String->getString();
467 if (
auto *B = dyn_cast<CXXBoolLiteralExpr>(S))
468 return B->getValue() ?
"true" :
"false";
479 operator int()
const {
return Id; }
490 std::vector<NodeId> RootIds;
492 std::vector<SNodeId> LeftMostDescendants;
499 int NumLeaves = setLeftMostDescendants();
500 computeKeyRoots(NumLeaves);
502 int getSize()
const {
return RootIds.size(); }
504 assert(Id > 0 && Id <=
getSize() &&
"Invalid subtree node index.");
505 return RootIds[Id - 1];
508 return Tree.
getNode(getIdInRoot(Id));
511 assert(Id > 0 && Id <=
getSize() &&
"Invalid subtree node index.");
512 return LeftMostDescendants[Id - 1];
524 int setLeftMostDescendants() {
526 LeftMostDescendants.resize(
getSize());
527 for (
int I = 0; I <
getSize(); ++I) {
531 assert(I == Tree.
PostorderIds[getIdInRoot(SI)] - getPostorderOffset() &&
532 "Postorder traversal in subtree should correspond to traversal in " 533 "the root tree by a constant offset.");
535 getPostorderOffset());
539 void computeKeyRoots(
int Leaves) {
540 KeyRoots.resize(Leaves);
541 std::unordered_set<int> Visited;
544 SNodeId LeftDesc = getLeftMostDescendant(I);
545 if (Visited.count(LeftDesc))
547 assert(K >= 0 &&
"K should be non-negative");
549 Visited.insert(LeftDesc);
562 std::unique_ptr<std::unique_ptr<double[]>[]> TreeDist, ForestDist;
567 : DiffImpl(DiffImpl), S1(T1, Id1), S2(T2, Id2) {
568 TreeDist = std::make_unique<std::unique_ptr<double[]>[]>(
570 ForestDist = std::make_unique<std::unique_ptr<double[]>[]>(
572 for (
int I = 0, E = S1.
getSize() + 1; I < E; ++I) {
573 TreeDist[I] = std::make_unique<double[]>(
size_t(S2.
getSize()) + 1);
574 ForestDist[I] = std::make_unique<double[]>(
size_t(S2.
getSize()) + 1);
579 std::vector<std::pair<NodeId, NodeId>> Matches;
580 std::vector<std::pair<SNodeId, SNodeId>> TreePairs;
584 bool RootNodePair =
true;
588 while (!TreePairs.empty()) {
589 SNodeId LastRow, LastCol, FirstRow, FirstCol, Row, Col;
590 std::tie(LastRow, LastCol) = TreePairs.back();
591 TreePairs.pop_back();
594 computeForestDist(LastRow, LastCol);
597 RootNodePair =
false;
605 while (Row > FirstRow || Col > FirstCol) {
606 if (Row > FirstRow &&
607 ForestDist[Row - 1][Col] + 1 == ForestDist[Row][Col]) {
609 }
else if (Col > FirstCol &&
610 ForestDist[Row][Col - 1] + 1 == ForestDist[Row][Col]) {
619 assert(DiffImpl.isMatchingPossible(Id1, Id2) &&
620 "These nodes must not be matched.");
621 Matches.emplace_back(Id1, Id2);
625 TreePairs.emplace_back(Row, Col);
641 static constexpr
double DeletionCost = 1;
642 static constexpr
double InsertionCost = 1;
650 void computeTreeDist() {
653 computeForestDist(Id1, Id2);
657 assert(Id1 > 0 && Id2 > 0 &&
"Expecting offsets greater than 0.");
661 ForestDist[LMD1][LMD2] = 0;
662 for (
SNodeId D1 = LMD1 + 1; D1 <= Id1; ++D1) {
663 ForestDist[D1][LMD2] = ForestDist[D1 - 1][LMD2] + DeletionCost;
664 for (
SNodeId D2 = LMD2 + 1; D2 <= Id2; ++D2) {
665 ForestDist[LMD1][D2] = ForestDist[LMD1][D2 - 1] + InsertionCost;
668 if (DLMD1 == LMD1 && DLMD2 == LMD2) {
669 double UpdateCost = getUpdateCost(D1, D2);
671 std::min({ForestDist[D1 - 1][D2] + DeletionCost,
672 ForestDist[D1][D2 - 1] + InsertionCost,
673 ForestDist[D1 - 1][D2 - 1] + UpdateCost});
674 TreeDist[D1][D2] = ForestDist[D1][D2];
677 std::min({ForestDist[D1 - 1][D2] + DeletionCost,
678 ForestDist[D1][D2 - 1] + InsertionCost,
679 ForestDist[DLMD1][DLMD2] + TreeDist[D1][D2]});
687 return ASTNode.getNodeKind();
693 if (
auto *ND = ASTNode.get<
NamedDecl>()) {
694 if (ND->getDeclName().isIdentifier())
695 return ND->getQualifiedNameAsString();
701 if (
auto *ND = ASTNode.get<
NamedDecl>()) {
702 if (ND->getDeclName().isIdentifier())
703 return ND->getName();
724 std::vector<NodeId> Container;
725 PriorityQueue<NodeId, std::vector<NodeId>, HeightLess> List;
729 :
Tree(Tree), Cmp(Tree), List(Cmp, Container) {}
731 void push(
NodeId id) { List.push(
id); }
733 std::vector<NodeId> pop() {
735 std::vector<NodeId> Result;
738 while (peekMax() == Max) {
739 Result.push_back(List.top());
746 int peekMax()
const {
749 return Tree.
getNode(List.top()).Height;
758 bool ASTDiff::Impl::identical(
NodeId Id1,
NodeId Id2)
const {
759 const Node &N1 = T1.getNode(Id1);
760 const Node &N2 = T2.getNode(Id2);
762 !isMatchingPossible(Id1, Id2) ||
763 T1.getNodeValue(Id1) != T2.getNodeValue(Id2))
771 bool ASTDiff::Impl::isMatchingPossible(
NodeId Id1,
NodeId Id2)
const {
772 return Options.isMatchingAllowed(T1.getNode(Id1), T2.getNode(Id2));
775 bool ASTDiff::Impl::haveSameParents(
const Mapping &M,
NodeId Id1,
777 NodeId P1 = T1.getNode(Id1).Parent;
778 NodeId P2 = T2.getNode(Id2).Parent;
783 void ASTDiff::Impl::addOptimalMapping(Mapping &M,
NodeId Id1,
785 if (
std::max(T1.getNumberOfDescendants(Id1), T2.getNumberOfDescendants(Id2)) >
790 for (
const auto &Tuple : R) {
792 NodeId Dst = Tuple.second;
793 if (!M.hasSrc(Src) && !M.hasDst(Dst))
798 double ASTDiff::Impl::getJaccardSimilarity(
const Mapping &M,
NodeId Id1,
800 int CommonDescendants = 0;
801 const Node &N1 = T1.getNode(Id1);
804 NodeId Dst = M.getDst(Src);
805 CommonDescendants += int(Dst.
isValid() && T2.isInSubtree(Dst, Id2));
808 double Denominator = T1.getNumberOfDescendants(Id1) - 1 +
809 T2.getNumberOfDescendants(Id2) - 1 - CommonDescendants;
811 assert(Denominator >= 0 &&
"Expected non-negative denominator.");
812 if (Denominator == 0)
814 return CommonDescendants / Denominator;
817 NodeId ASTDiff::Impl::findCandidate(
const Mapping &M,
NodeId Id1)
const {
819 double HighestSimilarity = 0.0;
821 if (!isMatchingPossible(Id1, Id2))
825 double Similarity = getJaccardSimilarity(M, Id1, Id2);
826 if (Similarity >= Options.MinSimilarity && Similarity > HighestSimilarity) {
827 HighestSimilarity = Similarity;
834 void ASTDiff::Impl::matchBottomUp(Mapping &M)
const {
836 for (
NodeId Id1 : Postorder) {
837 if (Id1 == T1.getRootId() && !M.hasSrc(T1.getRootId()) &&
838 !M.hasDst(T2.getRootId())) {
839 if (isMatchingPossible(T1.getRootId(), T2.getRootId())) {
840 M.link(T1.getRootId(), T2.getRootId());
841 addOptimalMapping(M, T1.getRootId(), T2.getRootId());
845 bool Matched = M.hasSrc(Id1);
846 const Node &N1 = T1.getNode(Id1);
847 bool MatchedChildren = llvm::any_of(
849 if (Matched || !MatchedChildren)
851 NodeId Id2 = findCandidate(M, Id1);
854 addOptimalMapping(M, Id1, Id2);
859 Mapping ASTDiff::Impl::matchTopDown()
const {
863 Mapping M(T1.getSize() + T2.getSize());
865 L1.push(T1.getRootId());
866 L2.push(T2.getRootId());
869 while (
std::min(Max1 = L1.peekMax(), Max2 = L2.peekMax()) >
881 std::vector<NodeId> H1, H2;
886 if (identical(Id1, Id2) && !M.hasSrc(Id1) && !M.hasDst(Id2)) {
887 for (
int I = 0, E = T1.getNumberOfDescendants(Id1); I < E; ++I)
888 M.link(Id1 + I, Id2 + I);
906 : T1(T1), T2(T2), Options(Options) {
920 if (!M.hasSrc(Id1)) {
921 T1.getMutableNode(Id1).Change =
Delete;
922 T1.getMutableNode(Id1).Shift -= 1;
926 if (!M.hasDst(Id2)) {
927 T2.getMutableNode(Id2).Change =
Insert;
928 T2.getMutableNode(Id2).Shift -= 1;
931 for (
NodeId Id1 : T1.NodesBfs) {
932 NodeId Id2 = M.getDst(Id1);
935 if (!haveSameParents(M, Id1, Id2) ||
936 T1.findPositionInParent(Id1,
true) !=
937 T2.findPositionInParent(Id2,
true)) {
938 T1.getMutableNode(Id1).Shift -= 1;
939 T2.getMutableNode(Id2).Shift -= 1;
942 for (
NodeId Id2 : T2.NodesBfs) {
943 NodeId Id1 = M.getSrc(Id2);
946 Node &N1 = T1.getMutableNode(Id1);
947 Node &N2 = T2.getMutableNode(Id2);
950 if (!haveSameParents(M, Id1, Id2) ||
951 T1.findPositionInParent(Id1,
true) !=
952 T2.findPositionInParent(Id2,
true)) {
955 if (T1.getNodeValue(Id1) != T2.getNodeValue(Id2)) {
963 : DiffImpl(
std::make_unique<
Impl>(*T1.TreeImpl, *T2.TreeImpl, Options)) {}
968 return DiffImpl->getMapped(SourceTree.
TreeImpl, Id);
973 this, AST.getTranslationUnitDecl(), AST)) {}
991 return TreeImpl->findPositionInParent(Id);
994 std::pair<unsigned, unsigned>
1002 if (ThisExpr->isImplicit())
1007 return {
Begin, End};
bool isBaseInitializer() const
Determine whether this initializer is initializing a base class.
llvm::Optional< std::string > getQualifiedIdentifier() const
A (possibly-)qualified type.
const Node & getNode(NodeId Id) const
Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be placed into a PointerUnion...
Stmt - This represents one statement.
const T * get() const
Retrieve the stored node as type T.
NodeId getMapped(const SyntaxTree &SourceTree, NodeId Id) const
Decl - This represents one declaration (or definition), e.g.
bool isInSubtree(NodeId Id, NodeId SubtreeRoot) const
ZhangShashaMatcher(const ASTDiff::Impl &DiffImpl, const SyntaxTree::Impl &T1, const SyntaxTree::Impl &T2, NodeId Id1, NodeId Id2)
bool isWritten() const
Determine whether this initializer is explicitly written in the source code.
ast_type_traits::ASTNodeKind getType() const
static std::vector< NodeId > getSubtreePostorder(const SyntaxTree::Impl &Tree, NodeId Root)
void computeChangeKinds(Mapping &M)
void computeMapping()
Matches nodes one-by-one based on their similarity.
llvm::Optional< StringRef > getIdentifier() const
const Node & getNode(SNodeId Id) const
std::vector< NodeId > NodesBfs
PreorderIterator end() const
std::vector< NodeId > Leaves
Describes how types, statements, expressions, and declarations should be printed. ...
NodeId getMapped(const std::unique_ptr< SyntaxTree::Impl > &Tree, NodeId Id) const
bool isValidNodeId(NodeId Id) const
std::vector< SNodeId > KeyRoots
SNodeId operator+(int Other) const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TypeSourceInfo * getTypeSourceInfo() const
Returns the declarator information for a base class or delegating initializer.
DynTypedNodeList getParents(const NodeT &Node)
Returns the parents of the given node (within the traversal scope).
std::string getNodeValue(NodeId Id) const
std::string getNodeValue(SNodeId Id) const
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
__DEVICE__ int max(int __a, int __b)
Implementation of Zhang and Shasha's Algorithm for tree edit distance.
Within a tree, this identifies a node by its preorder offset.
NodeId getPostorderOffset() const
Returns the postorder index of the leftmost descendant in the subtree.
ast_type_traits::DynTypedNode ASTNode
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
std::string getNodeValue(NodeId Id) const
Serialize the node attributes to a string representation.
bool isAnyMemberInitializer() const
std::unique_ptr< Impl > TreeImpl
SourceLocation getSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID. ...
FieldDecl * getAnyMember() const
int findPositionInParent(NodeId Id) const
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
std::string getStmtValue(const Stmt *S) const
Represents the this expression in C++.
int getNumberOfDescendants(NodeId Id) const
Impl(SyntaxTree *Parent, ASTContext &AST)
static std::string getInitializerValue(const CXXCtorInitializer *Init, const PrintingPolicy &TypePP)
ASTDiff(SyntaxTree &Src, SyntaxTree &Dst, const ComparisonOptions &Options)
bool isDelegatingInitializer() const
Determine whether this initializer is creating a delegating constructor.
Impl(SyntaxTree *Parent, typename std::enable_if< std::is_base_of< Decl, T >::value, T >::type *Node, ASTContext &AST)
NodeId RightMostDescendant
PreorderIterator end() const
static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
Identifies a node in a subtree by its postorder offset, starting at 1.
static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, const LangOptions &LangOpts)
Computes the source location just past the end of the token at this source location.
Represents a character-granular source range.
llvm::StringRef getAsString(SyncScope S)
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
static std::vector< NodeId > getSubtreeBfs(const SyntaxTree::Impl &Tree, NodeId Root)
PreorderIterator begin() const
DeclContext * getDeclContext()
const ASTContext & getASTContext() const
SourceRange getSourceRange() const
For nodes which represent textual entities in the source code, return their SourceRange.
SourceLocation getEnd() const
unsigned AnonymousTagLocations
When printing an anonymous tag name, also print the location of that entity (e.g., "enum <anonymous at t.h:10:5>").
unsigned getFileOffset(SourceLocation SpellingLoc) const
Returns the offset from the start of the file that the specified SourceLocation represents.
Encodes a location in the source.
PreorderIterator begin() const
SyntaxTree(ASTContext &AST)
Constructs a tree from a translation unit.
std::string getRelativeName(const NamedDecl *ND, const DeclContext *Context) const
std::vector< int > PostorderIds
StringRef getTypeLabel() const
std::vector< Node > Nodes
Nodes in preorder.
SyntaxTree objects represent subtrees of the AST.
SmallVector< NodeId, 4 > Children
Subtree(const SyntaxTree::Impl &Tree, NodeId SubtreeRoot)
NodeId getIdInRoot(SNodeId Id) const
bool isInMainFile(SourceLocation Loc) const
Returns whether the PresumedLoc for a given SourceLocation is in the main file.
ast_type_traits::DynTypedNode Node
static bool isNodeExcluded(const SourceManager &SrcMgr, T *N)
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
std::pair< unsigned, unsigned > getSourceRangeOffsets(const Node &N) const
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Node & getMutableNode(NodeId Id)
int findPositionInParent(NodeId Id, bool Shifted=false) const
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
const Type * getBaseClass() const
If this is a base class initializer, returns the type of the base class.
Represents the AST of a TranslationUnit.
NodeId LeftMostDescendant
Impl(SyntaxTree::Impl &T1, SyntaxTree::Impl &T2, const ComparisonOptions &Options)
A dynamically typed AST node container.
SNodeId getLeftMostDescendant(SNodeId Id) const
Represents a C++ base or member initializer.
SourceManager & getSourceManager()
std::string getDeclValue(const Decl *D) const
static const DeclContext * getEnclosingDeclContext(ASTContext &AST, const Stmt *S)
std::vector< std::pair< NodeId, NodeId > > getMatchingNodes()
__DEVICE__ int min(int __a, int __b)
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
std::string getQualifiedNameAsString() const
const Node & getNode(NodeId Id) const
A trivial tuple used to represent a source range.
static StringRef getOpcodeStr(Opcode Op)
getOpcodeStr - Turn an Opcode enum value into the punctuation char it corresponds to...
This represents a decl that may have a name.
Represents a Clang AST node, alongside some additional information.
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
This class handles loading and caching of source files into memory.
Impl(SyntaxTree *Parent, typename std::enable_if< std::is_base_of< Stmt, T >::value, T >::type *Node, ASTContext &AST)
QualType getType() const
Return the type wrapped by this type source info.
static bool isSpecializedNodeExcluded(CXXCtorInitializer *I)