Author: arphaman Date: Wed Aug 30 08:28:01 2017 New Revision: 312132 URL: http://llvm.org/viewvc/llvm-project?rev=312132&view=rev Log: Recommit r312127: [refactor] AST selection tree should contain syntactic form of PseudoObjectExpr
The new commit adjusts unittest test code compilation options so that the Objective-C code in the unittest can be parsed on non-macOS platforms. Original message: The AST selection finder now constructs a selection tree that contains only the syntactic form of PseudoObjectExpr. This form of selection tree is more meaningful when doing downstream analysis as we're interested in the syntactic features of the AST and the correct lexical parent relation. Modified: cfe/trunk/lib/Tooling/Refactoring/ASTSelection.cpp cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp cfe/trunk/unittests/Tooling/TestVisitor.h Modified: cfe/trunk/lib/Tooling/Refactoring/ASTSelection.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/ASTSelection.cpp?rev=312132&r1=312131&r2=312132&view=diff ============================================================================== --- cfe/trunk/lib/Tooling/Refactoring/ASTSelection.cpp (original) +++ cfe/trunk/lib/Tooling/Refactoring/ASTSelection.cpp Wed Aug 30 08:28:01 2017 @@ -10,6 +10,7 @@ #include "clang/Tooling/Refactoring/ASTSelection.h" #include "clang/AST/LexicallyOrderedRecursiveASTVisitor.h" #include "clang/Lex/Lexer.h" +#include "llvm/Support/SaveAndRestore.h" using namespace clang; using namespace tooling; @@ -60,6 +61,21 @@ public: return std::move(Result); } + bool TraversePseudoObjectExpr(PseudoObjectExpr *E) { + // Avoid traversing the semantic expressions. They should be handled by + // looking through the appropriate opaque expressions in order to build + // a meaningful selection tree. + llvm::SaveAndRestore<bool> LookThrough(LookThroughOpaqueValueExprs, true); + return TraverseStmt(E->getSyntacticForm()); + } + + bool TraverseOpaqueValueExpr(OpaqueValueExpr *E) { + if (!LookThroughOpaqueValueExprs) + return true; + llvm::SaveAndRestore<bool> LookThrough(LookThroughOpaqueValueExprs, false); + return TraverseStmt(E->getSourceExpr()); + } + bool TraverseDecl(Decl *D) { if (isa<TranslationUnitDecl>(D)) return LexicallyOrderedRecursiveASTVisitor::TraverseDecl(D); @@ -97,6 +113,8 @@ public: bool TraverseStmt(Stmt *S) { if (!S) return true; + if (auto *Opaque = dyn_cast<OpaqueValueExpr>(S)) + return TraverseOpaqueValueExpr(Opaque); // FIXME (Alex Lorenz): Improve handling for macro locations. SourceSelectionKind SelectionKind = selectionKindFor(CharSourceRange::getTokenRange(S->getSourceRange())); @@ -149,6 +167,10 @@ private: FileID TargetFile; const ASTContext &Context; std::vector<SelectedASTNode> SelectionStack; + /// Controls whether we can traverse through the OpaqueValueExpr. This is + /// typically enabled during the traversal of syntactic form for + /// PseudoObjectExprs. + bool LookThroughOpaqueValueExprs = false; }; } // end anonymous namespace Modified: cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp?rev=312132&r1=312131&r2=312132&view=diff ============================================================================== --- cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp (original) +++ cfe/trunk/unittests/Tooling/ASTSelectionTest.cpp Wed Aug 30 08:28:01 2017 @@ -513,4 +513,140 @@ TEST(ASTSelectionFinder, CorrectEndForOb SelectionFinderVisitor::Lang_OBJC); } +const SelectedASTNode &checkFnBody(const Optional<SelectedASTNode> &Node, + StringRef Name) { + EXPECT_TRUE(Node); + EXPECT_EQ(Node->Children.size(), 1u); + const auto &Fn = checkNode<FunctionDecl>( + Node->Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1, Name); + return checkNode<CompoundStmt>(Fn.Children[0], + SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1); +} + +TEST(ASTSelectionFinder, SelectObjectiveCPseudoObjectExprs) { + StringRef Source = R"( +@interface I +@property(readwrite) int prop; +@end +void selectProp(I *i) { +(void)i.prop; +i.prop = 21; +} + +typedef unsigned int size_t; +@interface NSMutableArray +- (id)objectAtIndexedSubscript:(size_t)index; +- (void)setObject:(id)object atIndexedSubscript:(size_t)index; +@end + +void selectSubscript(NSMutableArray *array, I *i) { + (void)array[10]; + array[i.prop] = i; +} +)"; + // Just 'i.prop'. + findSelectedASTNodes( + Source, {6, 7}, FileRange{{6, 7}, {6, 13}}, + [](Optional<SelectedASTNode> Node) { + const auto &CS = checkFnBody(Node, /*Name=*/"selectProp"); + const auto &CCast = checkNode<CStyleCastExpr>( + CS.Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1); + const auto &POE = checkNode<PseudoObjectExpr>( + CCast.Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1); + const auto &PRE = checkNode<ObjCPropertyRefExpr>( + POE.Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1); + const auto &Cast = checkNode<ImplicitCastExpr>( + PRE.Children[0], SourceSelectionKind::InsideSelection, + /*NumChildren=*/1); + checkNode<DeclRefExpr>(Cast.Children[0], + SourceSelectionKind::InsideSelection); + }, + SelectionFinderVisitor::Lang_OBJC); + // Just 'i.prop = 21' + findSelectedASTNodes( + Source, {7, 1}, FileRange{{7, 1}, {7, 12}}, + [](Optional<SelectedASTNode> Node) { + const auto &CS = checkFnBody(Node, /*Name=*/"selectProp"); + const auto &POE = checkNode<PseudoObjectExpr>( + CS.Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1); + const auto &BinOp = checkNode<BinaryOperator>( + POE.Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/2); + const auto &PRE = checkNode<ObjCPropertyRefExpr>( + BinOp.Children[0], SourceSelectionKind::InsideSelection, + /*NumChildren=*/1); + const auto &Cast = checkNode<ImplicitCastExpr>( + PRE.Children[0], SourceSelectionKind::InsideSelection, + /*NumChildren=*/1); + checkNode<DeclRefExpr>(Cast.Children[0], + SourceSelectionKind::InsideSelection); + checkNode<IntegerLiteral>(BinOp.Children[1], + SourceSelectionKind::InsideSelection); + }, + SelectionFinderVisitor::Lang_OBJC); + // Just 'array[10]' + findSelectedASTNodes( + Source, {17, 9}, FileRange{{17, 9}, {17, 18}}, + [](Optional<SelectedASTNode> Node) { + const auto &CS = checkFnBody(Node, /*Name=*/"selectSubscript"); + const auto &CCast = checkNode<CStyleCastExpr>( + CS.Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1); + const auto &POE = checkNode<PseudoObjectExpr>( + CCast.Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1); + const auto &SRE = checkNode<ObjCSubscriptRefExpr>( + POE.Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/2); + const auto &Cast = checkNode<ImplicitCastExpr>( + SRE.Children[0], SourceSelectionKind::InsideSelection, + /*NumChildren=*/1); + checkNode<DeclRefExpr>(Cast.Children[0], + SourceSelectionKind::InsideSelection); + checkNode<IntegerLiteral>(SRE.Children[1], + SourceSelectionKind::InsideSelection); + }, + SelectionFinderVisitor::Lang_OBJC); + // Just 'array[i.prop] = array' + findSelectedASTNodes( + Source, {18, 3}, FileRange{{18, 3}, {18, 20}}, + [](Optional<SelectedASTNode> Node) { + const auto &CS = checkFnBody(Node, /*Name=*/"selectSubscript"); + const auto &POE = checkNode<PseudoObjectExpr>( + CS.Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/1); + const auto &BinOp = checkNode<BinaryOperator>( + POE.Children[0], SourceSelectionKind::ContainsSelection, + /*NumChildren=*/2); + const auto &SRE = checkNode<ObjCSubscriptRefExpr>( + BinOp.Children[0], SourceSelectionKind::InsideSelection, + /*NumChildren=*/2); + const auto &Cast = checkNode<ImplicitCastExpr>( + SRE.Children[0], SourceSelectionKind::InsideSelection, + /*NumChildren=*/1); + checkNode<DeclRefExpr>(Cast.Children[0], + SourceSelectionKind::InsideSelection); + const auto &POE2 = checkNode<PseudoObjectExpr>( + SRE.Children[1], SourceSelectionKind::InsideSelection, + /*NumChildren=*/1); + const auto &PRE = checkNode<ObjCPropertyRefExpr>( + POE2.Children[0], SourceSelectionKind::InsideSelection, + /*NumChildren=*/1); + const auto &Cast2 = checkNode<ImplicitCastExpr>( + PRE.Children[0], SourceSelectionKind::InsideSelection, + /*NumChildren=*/1); + checkNode<DeclRefExpr>(Cast2.Children[0], + SourceSelectionKind::InsideSelection); + checkNode<DeclRefExpr>(BinOp.Children[1], + SourceSelectionKind::InsideSelection); + }, + SelectionFinderVisitor::Lang_OBJC); +} + } // end anonymous namespace Modified: cfe/trunk/unittests/Tooling/TestVisitor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/TestVisitor.h?rev=312132&r1=312131&r2=312132&view=diff ============================================================================== --- cfe/trunk/unittests/Tooling/TestVisitor.h (original) +++ cfe/trunk/unittests/Tooling/TestVisitor.h Wed Aug 30 08:28:01 2017 @@ -60,7 +60,10 @@ public: case Lang_CXX98: Args.push_back("-std=c++98"); break; case Lang_CXX11: Args.push_back("-std=c++11"); break; case Lang_CXX14: Args.push_back("-std=c++14"); break; - case Lang_OBJC: Args.push_back("-ObjC"); break; + case Lang_OBJC: + Args.push_back("-ObjC"); + Args.push_back("-fobjc-runtime=macosx-10.12.0"); + break; case Lang_OBJCXX11: Args.push_back("-ObjC++"); Args.push_back("-std=c++11"); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits