johannes updated this revision to Diff 110962. johannes added a comment. rebase
https://reviews.llvm.org/D36187 Files: include/clang/Tooling/ASTDiff/ASTDiff.h lib/Tooling/ASTDiff/ASTDiff.cpp test/Tooling/clang-diff-ast.cpp test/Tooling/clang-diff-basic.cpp test/Tooling/clang-diff-html.test test/Tooling/clang-diff-topdown.cpp
Index: test/Tooling/clang-diff-topdown.cpp =================================================================== --- test/Tooling/clang-diff-topdown.cpp +++ test/Tooling/clang-diff-topdown.cpp @@ -27,8 +27,19 @@ {{;;}} } +int x; + +namespace src { + int x; + int x1 = x + 1; + int x2 = ::x + 1; +} + +class A { int x = 1 + 1; void f() { int x1 = x; } }; + #else + void f1() { {{;}} @@ -45,4 +56,28 @@ ; } +int x; + +namespace dst { + int x; + // CHECK: Match DeclRefExpr: :x(17) to DeclRefExpr: :x(22) + int x1 = x + 1; + // CHECK: Match DeclRefExpr: x(21) to DeclRefExpr: x(26) + int x2 = ::x + 1; +} + +class B { + // Only the class name changed; it is not included in the field value, + // therefore there is no update. + // CHECK: Match FieldDecl: :x(int)(24) to FieldDecl: :x(int)(29) + // CHECK-NOT: Update FieldDecl: :x(int)(24) + int x = 1+1; + void f() { + // CHECK: Match MemberExpr: :x(32) to MemberExpr: :x(37) + // CHECK-NOT: Update MemberExpr: :x(32) + int x1 = B::x; + } + +}; + #endif Index: test/Tooling/clang-diff-html.test =================================================================== --- test/Tooling/clang-diff-html.test +++ test/Tooling/clang-diff-html.test @@ -11,12 +11,12 @@ // match, move // CHECK: <span id='L[[L:[0-9]+]]' tid='R[[R:[0-9]+]]' title='FunctionDecl // CHECK-NEXT: [[L]] -> [[R]] -// CHECK-NEXT: src::foo(void ())' class='u m'>void foo() +// CHECK-NEXT: :foo(void ())' class='m'>void foo() // match // CHECK: <span id='L[[L:[0-9]+]]' tid='R[[R:[0-9]+]]' title='FunctionDecl // CHECK-NEXT: [[L]] -> [[R]] -// CHECK-NEXT: src::main(void ())' class='u'>void main() +// CHECK-NEXT: :main(void ())'>void main() // deletion // CHECK: <span id='L[[L:[0-9]+]]' tid='R-1' title='IntegerLiteral Index: test/Tooling/clang-diff-basic.cpp =================================================================== --- test/Tooling/clang-diff-basic.cpp +++ test/Tooling/clang-diff-basic.cpp @@ -11,18 +11,18 @@ } } -// CHECK: Match DeclRefExpr: src::foo{{.*}} to DeclRefExpr: dst::inner::foo +// CHECK: Match DeclRefExpr: :foo{{.*}} to DeclRefExpr: :inner::foo void main() { inner::foo(); } // CHECK: Match StringLiteral: foo{{.*}} to StringLiteral: foo const char *b = "f" "o" "o"; // unsigned is canonicalized to unsigned int -// CHECK: Match TypedefDecl: src::nat;unsigned int;{{.*}} to TypedefDecl: dst::nat;unsigned int; +// CHECK: Match TypedefDecl: :nat;unsigned int;{{.*}} to TypedefDecl: :nat;unsigned int; typedef unsigned nat; -// CHECK: Match VarDecl: src::p(int){{.*}} to VarDecl: dst::prod(double) -// CHECK: Update VarDecl: src::p(int){{.*}} to dst::prod(double) +// CHECK: Match VarDecl: :p(int){{.*}} to VarDecl: :prod(double) +// CHECK: Update VarDecl: :p(int){{.*}} to :prod(double) // CHECK: Match BinaryOperator: *{{.*}} to BinaryOperator: * double prod = 1 * 2 * 10; // CHECK: Update DeclRefExpr Index: test/Tooling/clang-diff-ast.cpp =================================================================== --- test/Tooling/clang-diff-ast.cpp +++ test/Tooling/clang-diff-ast.cpp @@ -5,7 +5,7 @@ // CHECK: {{^}} NamespaceDecl: test;( namespace test { -// CHECK: {{^}} FunctionDecl: test::f( +// CHECK: {{^}} FunctionDecl: :f( // CHECK: CompoundStmt( void f() { // CHECK: VarDecl: i(int)( @@ -17,7 +17,7 @@ auto b = true; // CHECK: CallExpr( // CHECK-NOT: ImplicitCastExpr - // CHECK: DeclRefExpr: test::f( + // CHECK: DeclRefExpr: :f( f(); // CHECK: UnaryOperator: ++( ++i; @@ -41,7 +41,7 @@ // CHECK: CXXRecordDecl: X;X;( class X : Base { int m; - // CHECK: CXXMethodDecl: X::foo(const char *(int))( + // CHECK: CXXMethodDecl: :foo(const char *(int))( // CHECK: ParmVarDecl: i(int)( const char *foo(int i) { if (i == 0) @@ -56,12 +56,12 @@ int not_initialized; // All initialized members, bases and delegating initializers are are // appended, separated by commas. - // CHECK: CXXConstructorDecl: X::X(void (char, int))Base,X::m,( - X(char c, int) : Base(), m(0) { - // CHECK: MemberExpr: X::m( + // CHECK: CXXConstructorDecl: :X(void (char, int))Base,:m,( + X(char, int) : Base(), m(0) { + // CHECK: MemberExpr: :m( int x = m; } - // CHECK: CXXConstructorDecl: X::X(void (char))X,( + // CHECK: CXXConstructorDecl: :X(void (char))X,( X(char s) : X(s, 4) {} }; Index: lib/Tooling/ASTDiff/ASTDiff.cpp =================================================================== --- lib/Tooling/ASTDiff/ASTDiff.cpp +++ lib/Tooling/ASTDiff/ASTDiff.cpp @@ -111,24 +111,22 @@ /// Represents the AST of a TranslationUnit. class SyntaxTree::Impl { public: - /// Constructs a tree from the entire translation unit. - Impl(SyntaxTree *Parent, const ASTContext &AST); /// Constructs a tree from an AST node. - Impl(SyntaxTree *Parent, Decl *N, const ASTContext &AST); - Impl(SyntaxTree *Parent, Stmt *N, const ASTContext &AST); + Impl(SyntaxTree *Parent, Decl *N, ASTContext &AST); + Impl(SyntaxTree *Parent, Stmt *N, ASTContext &AST); template <class T> Impl(SyntaxTree *Parent, typename std::enable_if<std::is_base_of<Stmt, T>::value, T>::type *Node, - const ASTContext &AST) + ASTContext &AST) : Impl(Parent, dyn_cast<Stmt>(Node), AST) {} template <class T> Impl(SyntaxTree *Parent, typename std::enable_if<std::is_base_of<Decl, T>::value, T>::type *Node, - const ASTContext &AST) + ASTContext &AST) : Impl(Parent, dyn_cast<Decl>(Node), AST) {} SyntaxTree *Parent; - const ASTContext &AST; + ASTContext &AST; std::vector<NodeId> Leaves; // Maps preorder indices to postorder ones. std::vector<int> PostorderIds; @@ -270,7 +268,7 @@ }; } // end anonymous namespace -SyntaxTree::Impl::Impl(SyntaxTree *Parent, Decl *N, const ASTContext &AST) +SyntaxTree::Impl::Impl(SyntaxTree *Parent, Decl *N, ASTContext &AST) : Parent(Parent), AST(AST) { NodeCountVisitor NodeCounter(*this); NodeCounter.TraverseDecl(N); @@ -280,7 +278,7 @@ initTree(); } -SyntaxTree::Impl::Impl(SyntaxTree *Parent, Stmt *N, const ASTContext &AST) +SyntaxTree::Impl::Impl(SyntaxTree *Parent, Stmt *N, ASTContext &AST) : Parent(Parent), AST(AST) { NodeCountVisitor NodeCounter(*this); NodeCounter.TraverseStmt(N); @@ -365,6 +363,43 @@ llvm_unreachable("Node not found in parent's children."); } +// Returns the qualified name of ND. If it is subordinate to Context, +// then the prefix of the latter is removed from the returned value. +static std::string getRelativeName(const NamedDecl *ND, + const DeclContext *Context) { + std::string ContextPrefix; + if (auto *Namespace = dyn_cast<NamespaceDecl>(Context)) + ContextPrefix = Namespace->getQualifiedNameAsString(); + else if (auto *Tag = dyn_cast<TagDecl>(Context)) + ContextPrefix = Tag->getQualifiedNameAsString(); + std::string Val = ND->getQualifiedNameAsString(); + // Strip the qualifier, if Val refers to somthing in the current scope. + // But leave one leading ':' in place, so that we know that this is a + // relative path. + if (!ContextPrefix.empty() && + StringRef(Val).startswith(ContextPrefix)) + Val = Val.substr(ContextPrefix.size() + 1); + return Val; +} + +static std::string getRelativeName(const NamedDecl *ND) { + return getRelativeName(ND, ND->getDeclContext()); +} + +static const DeclContext *getEnclosingDeclContext(ASTContext &AST, + const Stmt *S) { + while (S) { + const auto &Parents = AST.getParents(*S); + if (Parents.empty()) + return nullptr; + const auto &P = Parents[0]; + if (const auto *D = P.get<Decl>()) + return D->getDeclContext(); + S = P.get<Stmt>(); + } + llvm_unreachable("Could not find Decl ancestor."); +} + std::string SyntaxTree::Impl::getNodeValue(NodeId Id) const { return getNodeValue(getNode(Id)); } @@ -384,8 +419,7 @@ TypePP.AnonymousTagLocations = false; if (auto *V = dyn_cast<ValueDecl>(D)) { - Value += V->getQualifiedNameAsString() + "(" + - V->getType().getAsString(TypePP) + ")"; + Value += getRelativeName(V) + "(" + V->getType().getAsString(TypePP) + ")"; if (auto *C = dyn_cast<CXXConstructorDecl>(D)) { for (auto *Init : C->inits()) { if (!Init->isWritten()) @@ -397,15 +431,15 @@ Value += C->getNameAsString(); } else { assert(Init->isAnyMemberInitializer()); - Value += Init->getMember()->getQualifiedNameAsString(); + Value += getRelativeName(Init->getMember()); } Value += ","; } } return Value; } if (auto *N = dyn_cast<NamedDecl>(D)) - Value += N->getQualifiedNameAsString() + ";"; + Value += getRelativeName(N) + ";"; if (auto *T = dyn_cast<TypedefNameDecl>(D)) return Value + T->getUnderlyingType().getAsString(TypePP) + ";"; if (auto *T = dyn_cast<TypeDecl>(D)) @@ -429,7 +463,7 @@ if (auto *B = dyn_cast<BinaryOperator>(S)) return B->getOpcodeStr(); if (auto *M = dyn_cast<MemberExpr>(S)) - return M->getMemberDecl()->getQualifiedNameAsString(); + return getRelativeName(M->getMemberDecl()); if (auto *I = dyn_cast<IntegerLiteral>(S)) { SmallString<256> Str; I->getValue().toString(Str, /*Radix=*/10, /*Signed=*/false); @@ -441,7 +475,7 @@ return Str.str(); } if (auto *D = dyn_cast<DeclRefExpr>(S)) - return D->getDecl()->getQualifiedNameAsString(); + return getRelativeName(D->getDecl(), getEnclosingDeclContext(AST, S)); if (auto *String = dyn_cast<StringLiteral>(S)) return String->getString(); if (auto *B = dyn_cast<CXXBoolLiteralExpr>(S)) @@ -950,7 +984,7 @@ return DiffImpl->getMapped(SourceTree.TreeImpl, Id); } -SyntaxTree::SyntaxTree(const ASTContext &AST) +SyntaxTree::SyntaxTree(ASTContext &AST) : TreeImpl(llvm::make_unique<SyntaxTree::Impl>( this, AST.getTranslationUnitDecl(), AST)) {} Index: include/clang/Tooling/ASTDiff/ASTDiff.h =================================================================== --- include/clang/Tooling/ASTDiff/ASTDiff.h +++ include/clang/Tooling/ASTDiff/ASTDiff.h @@ -68,10 +68,10 @@ class SyntaxTree { public: /// Constructs a tree from a translation unit. - SyntaxTree(const ASTContext &AST); + SyntaxTree(ASTContext &AST); /// Constructs a tree from any AST node. template <class T> - SyntaxTree(T *Node, const ASTContext &AST) + SyntaxTree(T *Node, ASTContext &AST) : TreeImpl(llvm::make_unique<Impl>(this, Node, AST)) {} SyntaxTree(SyntaxTree &&Other) = default; ~SyntaxTree();
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits