1 #include "TestingSupport.h" 2 #include "clang/AST/ASTContext.h" 3 #include "clang/AST/Decl.h" 4 #include "clang/AST/Stmt.h" 5 #include "clang/ASTMatchers/ASTMatchFinder.h" 6 #include "clang/ASTMatchers/ASTMatchers.h" 7 #include "clang/Analysis/CFG.h" 8 #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h" 9 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" 10 #include "clang/Basic/LLVM.h" 11 #include "clang/Basic/LangOptions.h" 12 #include "clang/Basic/SourceManager.h" 13 #include "clang/Basic/TokenKinds.h" 14 #include "clang/Lex/Lexer.h" 15 #include "clang/Serialization/PCHContainerOperations.h" 16 #include "clang/Tooling/ArgumentsAdjusters.h" 17 #include "clang/Tooling/Tooling.h" 18 #include "llvm/ADT/ArrayRef.h" 19 #include "llvm/ADT/DenseMap.h" 20 #include "llvm/ADT/Optional.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/ADT/StringSet.h" 23 #include "llvm/Support/Error.h" 24 #include "llvm/Testing/Support/Annotations.h" 25 #include <cassert> 26 #include <functional> 27 #include <memory> 28 #include <string> 29 #include <system_error> 30 #include <utility> 31 #include <vector> 32 33 using namespace clang; 34 using namespace dataflow; 35 using namespace ast_matchers; 36 37 static bool 38 isAnnotationDirectlyAfterStatement(const Stmt *Stmt, unsigned AnnotationBegin, 39 const SourceManager &SourceManager, 40 const LangOptions &LangOptions) { 41 auto NextToken = 42 Lexer::findNextToken(Stmt->getEndLoc(), SourceManager, LangOptions); 43 44 while (NextToken && SourceManager.getFileOffset(NextToken->getLocation()) < 45 AnnotationBegin) { 46 if (NextToken->isNot(tok::semi)) 47 return false; 48 49 NextToken = Lexer::findNextToken(NextToken->getEndLoc(), SourceManager, 50 LangOptions); 51 } 52 53 return true; 54 } 55 56 llvm::DenseMap<unsigned, std::string> 57 test::buildLineToAnnotationMapping(SourceManager &SM, 58 llvm::Annotations AnnotatedCode) { 59 llvm::DenseMap<unsigned, std::string> LineNumberToContent; 60 auto Code = AnnotatedCode.code(); 61 auto Annotations = AnnotatedCode.ranges(); 62 for (auto &AnnotationRange : Annotations) { 63 auto LineNumber = 64 SM.getPresumedLineNumber(SM.getLocForStartOfFile(SM.getMainFileID()) 65 .getLocWithOffset(AnnotationRange.Begin)); 66 auto Content = Code.slice(AnnotationRange.Begin, AnnotationRange.End).str(); 67 LineNumberToContent[LineNumber] = Content; 68 } 69 return LineNumberToContent; 70 } 71 72 llvm::Expected<llvm::DenseMap<const Stmt *, std::string>> 73 test::buildStatementToAnnotationMapping(const FunctionDecl *Func, 74 llvm::Annotations AnnotatedCode) { 75 llvm::DenseMap<const Stmt *, std::string> Result; 76 llvm::StringSet<> ExistingAnnotations; 77 78 auto StmtMatcher = 79 findAll(stmt(unless(anyOf(hasParent(expr()), hasParent(returnStmt())))) 80 .bind("stmt")); 81 82 // This map should stay sorted because the binding algorithm relies on the 83 // ordering of statement offsets 84 std::map<unsigned, const Stmt *> Stmts; 85 auto &Context = Func->getASTContext(); 86 auto &SourceManager = Context.getSourceManager(); 87 88 for (auto &Match : match(StmtMatcher, *Func->getBody(), Context)) { 89 const auto *S = Match.getNodeAs<Stmt>("stmt"); 90 unsigned Offset = SourceManager.getFileOffset(S->getEndLoc()); 91 Stmts[Offset] = S; 92 } 93 94 unsigned I = 0; 95 auto Annotations = AnnotatedCode.ranges(); 96 std::reverse(Annotations.begin(), Annotations.end()); 97 auto Code = AnnotatedCode.code(); 98 99 for (auto OffsetAndStmt = Stmts.rbegin(); OffsetAndStmt != Stmts.rend(); 100 OffsetAndStmt++) { 101 unsigned Offset = OffsetAndStmt->first; 102 const Stmt *Stmt = OffsetAndStmt->second; 103 104 if (I < Annotations.size() && Annotations[I].Begin >= Offset) { 105 auto Range = Annotations[I]; 106 107 if (!isAnnotationDirectlyAfterStatement(Stmt, Range.Begin, SourceManager, 108 Context.getLangOpts())) { 109 return llvm::createStringError( 110 std::make_error_code(std::errc::invalid_argument), 111 "Annotation is not placed after a statement: %s", 112 SourceManager.getLocForStartOfFile(SourceManager.getMainFileID()) 113 .getLocWithOffset(Offset) 114 .printToString(SourceManager) 115 .data()); 116 } 117 118 auto Annotation = Code.slice(Range.Begin, Range.End).str(); 119 if (!ExistingAnnotations.insert(Annotation).second) { 120 return llvm::createStringError( 121 std::make_error_code(std::errc::invalid_argument), 122 "Repeated use of annotation: %s", Annotation.data()); 123 } 124 Result[Stmt] = std::move(Annotation); 125 126 I++; 127 128 if (I < Annotations.size() && Annotations[I].Begin >= Offset) { 129 return llvm::createStringError( 130 std::make_error_code(std::errc::invalid_argument), 131 "Multiple annotations bound to the statement at the location: %s", 132 Stmt->getBeginLoc().printToString(SourceManager).data()); 133 } 134 } 135 } 136 137 if (I < Annotations.size()) { 138 return llvm::createStringError( 139 std::make_error_code(std::errc::invalid_argument), 140 "Not all annotations were bound to statements. Unbound annotation at: " 141 "%s", 142 SourceManager.getLocForStartOfFile(SourceManager.getMainFileID()) 143 .getLocWithOffset(Annotations[I].Begin) 144 .printToString(SourceManager) 145 .data()); 146 } 147 148 return Result; 149 } 150 151 const ValueDecl *test::findValueDecl(ASTContext &ASTCtx, llvm::StringRef Name) { 152 auto TargetNodes = match(valueDecl(hasName(Name)).bind("v"), ASTCtx); 153 assert(TargetNodes.size() == 1 && "Name must be unique"); 154 auto *const Result = selectFirst<ValueDecl>("v", TargetNodes); 155 assert(Result != nullptr); 156 return Result; 157 } 158