Index: lib/Tooling/ASTDiff/ASTDiff.cpp =================================================================== --- lib/Tooling/ASTDiff/ASTDiff.cpp +++ lib/Tooling/ASTDiff/ASTDiff.cpp @@ -183,12 +183,15 @@ static bool isSpecializedNodeExcluded(const Decl *D) { return D->isImplicit(); } static bool isSpecializedNodeExcluded(const Stmt *S) { return false; } +static bool isSpecializedNodeExcluded(CXXCtorInitializer *I) { + return !I->isWritten(); +} template static bool isNodeExcluded(ASTUnit &AST, T *N) { const SourceManager &SrcMgr = AST.getSourceManager(); if (!N) return true; - SourceLocation SLoc = N->getLocStart(); + SourceLocation SLoc = N->getSourceRange().getBegin(); if (SLoc.isValid()) { // Ignore everything from other files. if (!SrcMgr.isInMainFile(SLoc)) @@ -281,6 +284,14 @@ return true; } bool TraverseType(QualType T) { return true; } + bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { + if (isNodeExcluded(Tree.AST, Init)) + return true; + auto SavedState = PreTraverse(Init); + RecursiveASTVisitor::TraverseConstructorInitializer(Init); + PostTraverse(SavedState); + return true; + } }; } // end anonymous namespace @@ -419,6 +430,17 @@ return nullptr; } +static std::string getInitializerValue(const CXXCtorInitializer *Init, + const PrintingPolicy &TypePP) { + if (Init->isAnyMemberInitializer()) + return Init->getAnyMember()->getName(); + if (Init->isBaseInitializer()) + return QualType(Init->getBaseClass(), 0).getAsString(TypePP); + if (Init->isDelegatingInitializer()) + return Init->getTypeSourceInfo()->getType().getAsString(TypePP); + llvm_unreachable("Unknown initializer type"); +} + std::string SyntaxTree::Impl::getNodeValue(NodeId Id) const { return getNodeValue(getNode(Id)); } @@ -434,31 +456,15 @@ return getStmtValue(S); if (auto *D = DTN.get()) return getDeclValue(D); + if (auto *Init = DTN.get()) + return getInitializerValue(Init, TypePP); llvm_unreachable("Fatal: unhandled AST node.\n"); } std::string SyntaxTree::Impl::getDeclValue(const Decl *D) const { std::string Value; - if (auto *V = dyn_cast(D)) { - Value += getRelativeName(V) + "(" + V->getType().getAsString(TypePP) + ")"; - if (auto *C = dyn_cast(D)) { - for (auto *Init : C->inits()) { - if (!Init->isWritten()) - continue; - if (Init->isBaseInitializer()) { - Value += Init->getBaseClass()->getCanonicalTypeInternal().getAsString( - TypePP); - } else if (Init->isDelegatingInitializer()) { - Value += C->getNameAsString(); - } else { - assert(Init->isAnyMemberInitializer()); - Value += getRelativeName(Init->getMember()); - } - Value += ","; - } - } - return Value; - } + if (auto *V = dyn_cast(D)) + return getRelativeName(V) + "(" + V->getType().getAsString(TypePP) + ")"; if (auto *N = dyn_cast(D)) Value += getRelativeName(N) + ";"; if (auto *T = dyn_cast(D)) @@ -524,6 +530,8 @@ ConstStmtVisitor::Visit(S); else if (auto *D = DTN.get()) ConstDeclVisitor::Visit(D); + else if (auto *Init = DTN.get()) + addData(getInitializerValue(Init, Tree.TypePP)); else llvm_unreachable("Fatal: unhandled AST node.\n"); } @@ -943,7 +951,8 @@ NodeId Dst = M.getDst(Src); CommonDescendants += int(Dst.isValid() && T2.isInSubtree(Dst, Id2)); } - // We need to subtract 1 to get the number of descendants excluding the root. + // We need to subtract 1 to get the number of descendants excluding the + // root. double Denominator = T1.getNumberOfDescendants(Id1) - 1 + T2.getNumberOfDescendants(Id2) - 1 - CommonDescendants; // CommonDescendants is less than the size of one subtree. Index: test/Tooling/clang-diff-ast.cpp =================================================================== --- test/Tooling/clang-diff-ast.cpp +++ test/Tooling/clang-diff-ast.cpp @@ -54,14 +54,20 @@ // CHECK: AccessSpecDecl: public( public: int not_initialized; - // All initialized members, bases and delegating initializers are are - // appended, separated by commas. - // CHECK: CXXConstructorDecl: :X(void (char, int){{( __attribute__\(\(thiscall\)\))?}})Base,:m,( - X(char c, int) : Base(), m(0) { + // CHECK: CXXConstructorDecl: :X(void (char, int){{( __attribute__\(\(thiscall\)\))?}})( + // CHECK-NEXT: ParmVarDecl: s(char) + // CHECK-NEXT: ParmVarDecl: (int) + // CHECK-NEXT: CXXCtorInitializer: Base + // CHECK-NEXT: CXXConstructExpr + // CHECK-NEXT: CXXCtorInitializer: m + // CHECK-NEXT: IntegerLiteral: 0 + X(char s, int) : Base(), m(0) { + // CHECK-NEXT: CompoundStmt // CHECK: MemberExpr: :m( int x = m; } - // CHECK: CXXConstructorDecl: :X(void (char){{( __attribute__\(\(thiscall\)\))?}})X,( + // CHECK: CXXConstructorDecl: :X(void (char){{( __attribute__\(\(thiscall\)\))?}})( + // CHECK: CXXCtorInitializer: X X(char s) : X(s, 4) {} };