├── AST ├── ASTVisitor.cc ├── Makefile └── samples │ └── sample1.cc ├── CodeComplete ├── CodeComplete.cc ├── Makefile └── samples │ ├── sample1_l4c5.cc │ └── sample2_l6c9.cc ├── CompilationDatabase ├── CompilationDatabase.cc └── Makefile ├── Diagnosis ├── Diagnosis.cc ├── Makefile └── samples │ ├── sample1.cc │ └── sample2.cc ├── LICENSE.txt ├── README.md └── Token ├── Makefile ├── Tokenize.cc └── samples ├── sample1.cc └── sample2.cc /AST/ASTVisitor.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void show_spell(const CXCursor &cursor) { 6 | CXString spell = clang_getCursorSpelling(cursor); 7 | printf(" Text: %s\n", clang_getCString(spell)); 8 | clang_disposeString(spell); 9 | } 10 | 11 | void show_type(const CXCursor &cursor) { 12 | CXType type = clang_getCursorType(cursor); 13 | CXString typeName = clang_getTypeSpelling(type); 14 | CXTypeKind typeKind = type.kind; 15 | CXString typeKindName = clang_getTypeKindSpelling(typeKind); 16 | printf(" Type: %s\n", clang_getCString(typeName)); 17 | printf(" TypeKind: %s\n", clang_getCString(typeKindName)); 18 | clang_disposeString(typeName); 19 | clang_disposeString(typeKindName); 20 | } 21 | 22 | void show_linkage(const CXCursor &cursor) { 23 | CXLinkageKind linkage = clang_getCursorLinkage(cursor); 24 | const char *linkageName; 25 | switch (linkage) { 26 | case CXLinkage_Invalid: linkageName = "Invalid"; break; 27 | case CXLinkage_NoLinkage: linkageName = "NoLinkage"; break; 28 | case CXLinkage_Internal: linkageName = "Internal"; break; 29 | case CXLinkage_UniqueExternal: linkageName = "UniqueExternal"; break; 30 | case CXLinkage_External: linkageName = "External"; break; 31 | default: linkageName = "Unknown"; break; 32 | } 33 | printf(" Linkage: %s\n", linkageName); 34 | } 35 | 36 | void show_parent(const CXCursor &cursor, const CXCursor &parent) { 37 | CXCursor semaParent = clang_getCursorSemanticParent(cursor); 38 | CXCursor lexParent = clang_getCursorLexicalParent(cursor); 39 | CXString parentName = clang_getCursorSpelling(parent); 40 | CXString semaParentName = clang_getCursorSpelling(semaParent); 41 | CXString lexParentName = clang_getCursorSpelling(lexParent); 42 | printf(" Parent: parent:%s semantic:%s lexicial:%s\n", 43 | clang_getCString(parentName), 44 | clang_getCString(semaParentName), 45 | clang_getCString(lexParentName)); 46 | 47 | clang_disposeString(parentName); 48 | clang_disposeString(semaParentName); 49 | clang_disposeString(lexParentName); 50 | } 51 | 52 | void show_location(const CXCursor &cursor) { 53 | CXSourceLocation loc = clang_getCursorLocation(cursor); 54 | CXFile file; 55 | unsigned line, column, offset; 56 | clang_getSpellingLocation(loc, &file, &line, &column, &offset); 57 | CXString fileName = clang_getFileName(file); 58 | printf(" Location: %s:%d:%d:%d\n", 59 | clang_getCString(fileName), line, column, offset); 60 | clang_disposeString(fileName); 61 | } 62 | 63 | void show_usr(const CXCursor &cursor) { 64 | CXString usr = clang_getCursorUSR(cursor); 65 | printf(" USR: %s\n", clang_getCString(usr)); 66 | clang_disposeString(usr); 67 | } 68 | 69 | void show_cursor_kind(const CXCursor &cursor) { 70 | CXCursorKind curKind = clang_getCursorKind(cursor); 71 | CXString curKindName = clang_getCursorKindSpelling(curKind); 72 | 73 | const char *type; 74 | if (clang_isAttribute(curKind)) type = "Attribute"; 75 | else if (clang_isDeclaration(curKind)) type = "Declaration"; 76 | else if (clang_isExpression(curKind)) type = "Expression"; 77 | else if (clang_isInvalid(curKind)) type = "Invalid"; 78 | else if (clang_isPreprocessing(curKind)) type = "Preprocessing"; 79 | else if (clang_isReference(curKind)) type = "Reference"; 80 | else if (clang_isStatement(curKind)) type = "Statement"; 81 | else if (clang_isTranslationUnit(curKind)) type = "TranslationUnit"; 82 | else if (clang_isUnexposed(curKind)) type = "Unexposed"; 83 | else type = "Unknown"; 84 | 85 | printf(" CursorKind: %s\n", clang_getCString(curKindName)); 86 | printf(" CursorKindType: %s\n", type); 87 | clang_disposeString(curKindName); 88 | } 89 | 90 | void show_included_file(const CXCursor &cursor) { 91 | CXFile included = clang_getIncludedFile(cursor); 92 | if (included == 0) return; 93 | 94 | CXString includedFileName = clang_getFileName(included); 95 | printf(" included file: %s\n", clang_getCString(includedFileName)); 96 | clang_disposeString(includedFileName); 97 | } 98 | 99 | CXChildVisitResult visitChildrenCallback(CXCursor cursor, 100 | CXCursor parent, 101 | CXClientData client_data) { 102 | unsigned level = *(unsigned *)client_data; 103 | printf(" Level: %d\n", level); 104 | 105 | show_spell(cursor); 106 | show_linkage(cursor); 107 | show_cursor_kind(cursor); 108 | show_type(cursor); 109 | show_parent(cursor, parent); 110 | show_location(cursor); 111 | show_usr(cursor); 112 | show_included_file(cursor); 113 | printf("\n"); 114 | 115 | // visit children recursively 116 | unsigned next = level + 1; 117 | clang_visitChildren(cursor, visitChildrenCallback, &next); 118 | 119 | return CXChildVisit_Continue; 120 | } 121 | 122 | void show_clang_version(void) { 123 | CXString version = clang_getClangVersion(); 124 | printf("%s\n", clang_getCString(version)); 125 | clang_disposeString(version); 126 | } 127 | 128 | int main(int argc, char **argv) { 129 | if (argc != 2) { 130 | printf("ASTVisitor AST_file\n"); 131 | exit(1); 132 | } 133 | 134 | show_clang_version(); 135 | 136 | const auto filename = argv[1]; 137 | 138 | // create index w/ excludeDeclsFromPCH = 1, displayDiagnostics=1. 139 | CXIndex index = clang_createIndex(1, 1); 140 | 141 | // load a *.ast file. 142 | CXTranslationUnit tu = clang_createTranslationUnit(index, filename); 143 | if (tu == NULL) { 144 | printf("Cannot create translation unit\n"); 145 | return 1; 146 | } 147 | 148 | unsigned level = 0; 149 | CXCursor cursor = clang_getTranslationUnitCursor(tu); 150 | clang_visitChildren(cursor, visitChildrenCallback, &level); 151 | 152 | clang_disposeTranslationUnit(tu); 153 | clang_disposeIndex(index); 154 | return 0; 155 | } 156 | -------------------------------------------------------------------------------- /AST/Makefile: -------------------------------------------------------------------------------- 1 | 2 | UNAME_S:=$(shell uname -s) 3 | 4 | TARGET=ASTVisitor 5 | CXX=clang 6 | CFLAGS=-std=c++11 -O2 -Wall -Wextra 7 | ifeq ($(UNAME_S), Darwin) 8 | CFLAGS+=-stdlib=libstdc++ 9 | endif 10 | FLAGS=`llvm-config --cxxflags --ldflags` -lclang $(CFLAGS) 11 | 12 | SAMPLE_DIR=samples 13 | SAMPLES:=$(wildcard $(SAMPLE_DIR)/*.cc) 14 | SAMPLES_OUT:=$(subst .cc,_out.txt,$(SAMPLES)) 15 | 16 | all: $(TARGET) 17 | 18 | $(TARGET): $(TARGET).cc 19 | $(CXX) $(TARGET).cc -o $(TARGET) $(FLAGS) 20 | 21 | run: $(SAMPLES_OUT) 22 | 23 | $(SAMPLE_DIR)/%_out.txt: $(TARGET) $(SAMPLE_DIR)/%.cc 24 | $(CXX) $(SAMPLE_DIR)/$*.cc -o $(SAMPLE_DIR)/$*.ast -emit-ast -std=c++11 25 | ./$(TARGET) $(SAMPLE_DIR)/$*.ast > $@ 2>&1 26 | 27 | clean: 28 | @find . -name '*~' | xargs rm -f 29 | @rm -f $(TARGET) $(SAMPLES_OUT) $(SAMPLE_DIR)/*.ast 30 | 31 | .PHONY: check-syntax 32 | check-syntax: 33 | @$(CXX) -c $(CHK_SOURCES) -fsyntax-only $(FLAGS) 34 | -------------------------------------------------------------------------------- /AST/samples/sample1.cc: -------------------------------------------------------------------------------- 1 | typedef int sampleInt; 2 | 3 | class C { 4 | public: 5 | void f(); 6 | }; 7 | 8 | void C::f() { } 9 | 10 | void hoge() { 11 | sampleInt a = 10; 12 | C c; 13 | c.f(); 14 | } 15 | -------------------------------------------------------------------------------- /CodeComplete/CodeComplete.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | const char *_getCompleteChunkKindSpelling(CXCompletionChunkKind chunkKind) { 6 | switch (chunkKind) { 7 | case CXCompletionChunk_Optional: return "Optional"; break; 8 | case CXCompletionChunk_TypedText: return "TypedText"; break; 9 | case CXCompletionChunk_Text: return "Text"; break; 10 | case CXCompletionChunk_Placeholder: return "Placeholder"; break; 11 | case CXCompletionChunk_Informative: return "Informative"; break; 12 | case CXCompletionChunk_CurrentParameter: return "CurrentParameter"; break; 13 | case CXCompletionChunk_LeftParen: return "LeftParen"; break; 14 | case CXCompletionChunk_RightParen: return "RightParen"; break; 15 | case CXCompletionChunk_LeftBracket: return "LeftBracket"; break; 16 | case CXCompletionChunk_RightBracket: return "RightBracket"; break; 17 | case CXCompletionChunk_LeftBrace: return "LeftBrace"; break; 18 | case CXCompletionChunk_RightBrace: return "RightBrace"; break; 19 | case CXCompletionChunk_LeftAngle: return "LeftAngle"; break; 20 | case CXCompletionChunk_RightAngle: return "RightAngle"; break; 21 | case CXCompletionChunk_Comma: return "Comma"; break; 22 | case CXCompletionChunk_ResultType: return "ResultType"; break; 23 | case CXCompletionChunk_Colon: return "Colon"; break; 24 | case CXCompletionChunk_SemiColon: return "SemiColon"; break; 25 | case CXCompletionChunk_Equal: return "Equal"; break; 26 | case CXCompletionChunk_HorizontalSpace: return "HorizontalSpace"; break; 27 | case CXCompletionChunk_VerticalSpace: return "VerticalSpace"; break; 28 | default: return "Unknown"; break; 29 | } 30 | } 31 | 32 | const char *_getCompletionAvailabilitySpelling(CXAvailabilityKind availavility) { 33 | switch (availavility) { 34 | case CXAvailability_Available: return "Available"; break; 35 | case CXAvailability_Deprecated: return "Deprecated"; break; 36 | case CXAvailability_NotAvailable: return "NotAvailable"; break; 37 | case CXAvailability_NotAccessible: return "NotAccessible"; break; 38 | default: return "Unknown"; break; 39 | } 40 | } 41 | 42 | const char *_getKindTypeName(CXCursor cursor) { 43 | CXCursorKind curKind = clang_getCursorKind(cursor); 44 | const char *type; 45 | if (clang_isAttribute(curKind)) { 46 | type = "Attribute"; 47 | } else if (clang_isDeclaration(curKind)) { 48 | type = "Declaration"; 49 | } else if (clang_isExpression(curKind)) { 50 | type = "Expression"; 51 | } else if (clang_isInvalid(curKind)) { 52 | type = "Invalid"; 53 | } else if (clang_isPreprocessing(curKind)) { 54 | type = "Preprocessing"; 55 | } else if (clang_isReference(curKind)) { 56 | type = "Reference"; 57 | } else if (clang_isStatement(curKind)) { 58 | type = "Statement"; 59 | } else if (clang_isTranslationUnit(curKind)) { 60 | type = "TranslationUnit"; 61 | } else if (clang_isUnexposed(curKind)) { 62 | type = "Unexposed"; 63 | } else { 64 | type = "Unknown"; 65 | } 66 | return type; 67 | } 68 | 69 | void show_completion_results(CXCodeCompleteResults *compResults) { 70 | printf("=== show results ===\n"); 71 | unsigned isIncomplete; 72 | CXCursorKind kind = clang_codeCompleteGetContainerKind(compResults, &isIncomplete); 73 | printf("Complete: %d\n", !isIncomplete); 74 | CXString kindName = clang_getCursorKindSpelling(kind); 75 | printf("Kind: %s\n", clang_getCString(kindName)); 76 | clang_disposeString(kindName); 77 | 78 | CXString usr = clang_codeCompleteGetContainerUSR(compResults); 79 | printf("USR: %s\n", clang_getCString(usr)); 80 | clang_disposeString(usr); 81 | 82 | unsigned long long context = clang_codeCompleteGetContexts(compResults); 83 | printf("Context: %llu\n", context); 84 | printf("\n"); 85 | 86 | // show completion results 87 | printf("=== show completion results ===\n"); 88 | printf("CodeCompleationResultsNum: %d\n", compResults->NumResults); 89 | for (auto i = 0U; i < compResults->NumResults; i++) { 90 | printf("Results: %d\n", i); 91 | const CXCompletionResult &result = compResults->Results[i]; 92 | const CXCompletionString &compString = result.CompletionString; 93 | const CXCursorKind kind = result.CursorKind; 94 | 95 | CXString kindName = clang_getCursorKindSpelling(kind); 96 | printf(" Kind: %s\n", clang_getCString(kindName)); 97 | clang_disposeString(kindName); 98 | 99 | CXAvailabilityKind availavility = clang_getCompletionAvailability(compString); 100 | const char *availavilityText = _getCompletionAvailabilitySpelling(availavility); 101 | printf(" Availavility: %s\n", availavilityText); 102 | 103 | unsigned priority = clang_getCompletionPriority(compString); 104 | printf(" Priority: %d\n", priority); 105 | 106 | CXString comment = clang_getCompletionBriefComment(compString); 107 | printf(" Comment: %s\n", clang_getCString(comment)); 108 | clang_disposeString(comment); 109 | 110 | unsigned numChunks = clang_getNumCompletionChunks(compString); 111 | printf(" NumChunks: %d\n", numChunks); 112 | for (auto j = 0U; j < numChunks; j++) { 113 | CXString chunkText = clang_getCompletionChunkText(compString, j); 114 | CXCompletionChunkKind chunkKind = clang_getCompletionChunkKind(compString, j); 115 | printf(" Kind: %s Text: %s\n", 116 | _getCompleteChunkKindSpelling(chunkKind), 117 | clang_getCString(chunkText)); 118 | 119 | // TODO: check child chunks when CXCompletionChunk_Optional 120 | // CXCompletionString child = clang_getCompletionChunkCompletionString(compString); 121 | clang_disposeString(chunkText); 122 | } 123 | 124 | unsigned numAnnotations = clang_getCompletionNumAnnotations(compString); 125 | printf(" NumAnnotation: %d\n", numAnnotations); 126 | for (auto j = 0U; j < numAnnotations; j++) { 127 | CXString annoText = clang_getCompletionAnnotation(compString, j); 128 | printf(" Annotation: %s\n", clang_getCString(annoText)); 129 | clang_disposeString(annoText); 130 | } 131 | printf("\n"); 132 | } 133 | } 134 | 135 | void show_diagnosis(const CXTranslationUnit &tu, 136 | CXCodeCompleteResults *compResults) { 137 | printf("=== show diagnosis ===\n"); 138 | unsigned numDiag = clang_codeCompleteGetNumDiagnostics(compResults); 139 | printf("NumDiagnosis:%d\n", numDiag); 140 | for (auto i = 0U; i < numDiag; i++) { 141 | clang_codeCompleteGetDiagnostic(compResults, i); 142 | CXDiagnostic diag = clang_getDiagnostic(tu, i); 143 | CXString diagText = clang_getDiagnosticSpelling(diag); 144 | printf(" Diagnosis: %s\n", clang_getCString(diagText)); 145 | clang_disposeString(diagText); 146 | } 147 | } 148 | 149 | void show_clang_version(void) { 150 | CXString version = clang_getClangVersion(); 151 | printf("%s\n", clang_getCString(version)); 152 | clang_disposeString(version); 153 | } 154 | 155 | int main(int argc, char **argv) { 156 | if (argc < 4) { 157 | printf("CodeComplete filename line column [options ...]\n"); 158 | exit(1); 159 | } 160 | 161 | show_clang_version(); 162 | 163 | const auto filename = argv[1]; 164 | unsigned lineno = atoi(argv[2]); 165 | unsigned columnno = atoi(argv[3]); 166 | const auto cmdArgs = &argv[4]; 167 | auto numArgs = argc - 4; 168 | 169 | // create index w/ excludeDeclsFromPCH = 1, displayDiagnostics=1. 170 | CXIndex index = clang_createIndex(1, 0); 171 | 172 | // create Translation Unit 173 | CXTranslationUnit tu = clang_parseTranslationUnit(index, filename, cmdArgs, numArgs, NULL, 0, CXTranslationUnit_PrecompiledPreamble | CXTranslationUnit_Incomplete ); 174 | if (tu == NULL) { 175 | printf("Cannot parse translation unit\n"); 176 | exit(1); 177 | } 178 | 179 | // Code Completion 180 | CXCodeCompleteResults *compResults; 181 | compResults = clang_codeCompleteAt(tu, filename, lineno, columnno, 182 | NULL, 0, clang_defaultCodeCompleteOptions()); 183 | if (compResults == NULL) { 184 | printf("Invalid\n"); 185 | exit(1); 186 | } 187 | 188 | // show Completion results 189 | show_completion_results(compResults); 190 | 191 | // show Diagnosis 192 | show_diagnosis(tu, compResults); 193 | 194 | clang_disposeCodeCompleteResults(compResults); 195 | clang_disposeTranslationUnit(tu); 196 | clang_disposeIndex(index); 197 | return 0; 198 | } 199 | -------------------------------------------------------------------------------- /CodeComplete/Makefile: -------------------------------------------------------------------------------- 1 | 2 | UNAME_S:=$(shell uname -s) 3 | 4 | TARGET=CodeComplete 5 | CXX=clang 6 | CFLAGS=-std=c++11 -O2 -Wall -Wextra 7 | ifeq ($(UNAME_S), Darwin) 8 | CLANG_STDLIB:=-stdlib=libstdc++ 9 | CFLAGS+=$(CLANG_STDLIB) 10 | endif 11 | FLAGS=`llvm-config --cxxflags --ldflags` -lclang $(CFLAGS) 12 | 13 | SAMPLE_DIR=samples 14 | SAMPLES:=$(wildcard $(SAMPLE_DIR)/*.cc) 15 | SAMPLES_OUT:=$(subst .cc,_out.txt,$(SAMPLES)) 16 | 17 | all: $(TARGET) 18 | 19 | $(TARGET): $(TARGET).cc 20 | $(CXX) $(TARGET).cc -o $(TARGET) $(FLAGS) 21 | 22 | run: $(SAMPLES_OUT) 23 | 24 | $(SAMPLE_DIR)/%_out.txt: $(TARGET) 25 | -./$(TARGET) $(SAMPLE_DIR)/$*.cc $(shell echo $* | sed 's/.*_l\([0-9][0-9]*\)c\([0-9][0-9]*\).*/\1 \2/') $(CLANG_STDLIB) > $@ 2>&1 26 | 27 | clean: 28 | @find . -name '*~' | xargs rm -f 29 | @rm -f $(TARGET) $(SAMPLES_OUT) 30 | -------------------------------------------------------------------------------- /CodeComplete/samples/sample1_l4c5.cc: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) { 3 | std::vector v; 4 | v.push 5 | } 6 | -------------------------------------------------------------------------------- /CodeComplete/samples/sample2_l6c9.cc: -------------------------------------------------------------------------------- 1 | namespace hoge { 2 | void put(int a); 3 | } 4 | 5 | int main(void) { 6 | hoge:: 7 | } 8 | -------------------------------------------------------------------------------- /CompilationDatabase/CompilationDatabase.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void show_clang_version(void) { 7 | CXString version = clang_getClangVersion(); 8 | printf("%s\n", clang_getCString(version)); 9 | clang_disposeString(version); 10 | } 11 | 12 | int main(int argc, char **argv) { 13 | if (argc != 2) { 14 | printf("CompilationDatabase directory\n"); 15 | exit(1); 16 | } 17 | 18 | show_clang_version(); 19 | 20 | CXCompilationDatabase_Error error; 21 | CXCompilationDatabase db = clang_CompilationDatabase_fromDirectory(argv[1], &error); 22 | switch (error) { 23 | case CXCompilationDatabase_NoError: 24 | break; 25 | case CXCompilationDatabase_CanNotLoadDatabase: 26 | printf("Cannot load database\n"); 27 | exit(1); 28 | default: 29 | printf("unknown return\n"); 30 | exit(1); 31 | } 32 | 33 | CXCompileCommands cmds = clang_CompilationDatabase_getAllCompileCommands(db); 34 | auto numCmds = clang_CompileCommands_getSize(cmds); 35 | printf("CommandNum: %d\n", numCmds); 36 | 37 | for (auto i = 0U; i < numCmds; i++) { 38 | CXCompileCommands cmd = clang_CompileCommands_getCommand(cmds, i); 39 | auto numArgs = clang_CompileCommand_getNumArgs(cmd); 40 | printf(" CommandArgs: %d\n", numArgs); 41 | for (auto j = 0U; j < numArgs; j++) { 42 | CXString arg = clang_CompileCommand_getArg(cmd, j); 43 | printf(" %s \n", clang_getCString(arg)); 44 | clang_disposeString(arg); 45 | } 46 | } 47 | 48 | clang_CompileCommands_dispose(cmds); 49 | clang_CompilationDatabase_dispose(db); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /CompilationDatabase/Makefile: -------------------------------------------------------------------------------- 1 | 2 | UNAME_S:=$(shell uname -s) 3 | 4 | TARGET=CompilationDatabase 5 | CXX=clang 6 | CFLAGS=-std=c++11 -O2 -Wall -Wextra 7 | ifeq ($(UNAME_S), Darwin) 8 | CFLAGS+=-stdlib=libstdc++ 9 | endif 10 | FLAGS=`llvm-config --cxxflags --ldflags` -lclang $(CFLAGS) 11 | 12 | SAMPLE_DIR=samples 13 | SAMPLES:=$(wildcard $(SAMPLE_DIR)/*.cc) 14 | SAMPLES_OUT:=$(subst .cc,_out.txt,$(SAMPLES)) 15 | 16 | all: $(TARGET) 17 | 18 | $(TARGET): $(TARGET).cc 19 | $(CXX) $(TARGET).cc -o $(TARGET) $(FLAGS) 20 | 21 | run: $(SAMPLES_OUT) 22 | 23 | $(SAMPLE_DIR)/%_out.txt: $(TARGET) $(SAMPLE_DIR)/%.cc 24 | ./$(TARGET) $(SAMPLE_DIR)/$*.cc `llvm-config --cxxflags` > $@ 2>&1 25 | 26 | clean: 27 | @find . -name '*~' | xargs rm -f 28 | @rm -f $(TARGET) $(SAMPLES_OUT) 29 | 30 | .PHONY: check-syntax 31 | check-syntax: 32 | @$(CXX) -c $(CHK_SOURCES) -fsyntax-only $(FLAGS) 33 | -------------------------------------------------------------------------------- /Diagnosis/Diagnosis.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void show_diagnosis_format(const CXDiagnostic &diag) { 6 | unsigned formatOption = CXDiagnostic_DisplaySourceLocation | 7 | CXDiagnostic_DisplayColumn | 8 | CXDiagnostic_DisplaySourceRanges | 9 | CXDiagnostic_DisplayOption | 10 | CXDiagnostic_DisplayCategoryId| 11 | CXDiagnostic_DisplayCategoryName; 12 | CXString format = clang_formatDiagnostic(diag, formatOption); 13 | printf(" Format: %s\n", clang_getCString(format)); 14 | clang_disposeString(format); 15 | } 16 | 17 | void show_diagnosis_severity(const CXDiagnostic &diag) { 18 | CXDiagnosticSeverity severity = clang_getDiagnosticSeverity(diag); 19 | const char *severityText; 20 | switch (severity) { 21 | case CXDiagnostic_Ignored: severityText = "Ignored"; break; 22 | case CXDiagnostic_Note: severityText = "Note"; break; 23 | case CXDiagnostic_Warning: severityText = "Warning"; break; 24 | case CXDiagnostic_Error: severityText = "Error"; break; 25 | case CXDiagnostic_Fatal: severityText = "Fatal"; break; 26 | default: severityText = "Unknown"; break; 27 | } 28 | printf(" Severity: %s\n", severityText); 29 | } 30 | 31 | void show_diagnosis_location(const CXDiagnostic &diag) { 32 | CXSourceLocation loc = clang_getDiagnosticLocation(diag); 33 | CXFile file; 34 | unsigned line, column, offset; 35 | clang_getSpellingLocation(loc, &file, &line, &column, &offset); 36 | CXString fileText = clang_getFileName(file); 37 | printf(" Location: %s:%d:%d:%d\n", 38 | clang_getCString(fileText), line, column, offset); 39 | clang_disposeString(fileText); 40 | } 41 | 42 | void show_diagnosis_category(const CXDiagnostic &diag) { 43 | CXString catText = clang_getDiagnosticCategoryText(diag); 44 | printf(" Category: %s\n", clang_getCString(catText)); 45 | clang_disposeString(catText); 46 | } 47 | 48 | void show_diagnosis_range(const CXDiagnostic &diag) { 49 | CXFile file; 50 | unsigned line, column, offset; 51 | CXString fileText; 52 | 53 | unsigned numRange = clang_getDiagnosticNumRanges(diag); 54 | printf(" NumRange: %d\n", numRange); 55 | for (auto j = 0U; j < numRange; j++) { 56 | CXSourceRange range = clang_getDiagnosticRange(diag, j); 57 | printf(" Range %d\n", j); 58 | 59 | CXSourceLocation start = clang_getRangeStart(range); 60 | clang_getSpellingLocation(start, &file, &line, &column, &offset); 61 | fileText =clang_getFileName(file); 62 | printf(" Start: %s:%d:%d:%d\n", 63 | clang_getCString(fileText), line, column, offset); 64 | clang_disposeString(fileText); 65 | 66 | CXSourceLocation end = clang_getRangeEnd(range); 67 | clang_getSpellingLocation(end, &file, &line, &column, &offset); 68 | fileText =clang_getFileName(file); 69 | printf(" End: %s:%d:%d:%d\n", 70 | clang_getCString(fileText), line, column, offset); 71 | clang_disposeString(fileText); 72 | } 73 | } 74 | 75 | void show_diagnosis_fixit(const CXDiagnostic &diag) { 76 | unsigned numFixit = clang_getDiagnosticNumFixIts(diag); 77 | printf(" NumFixit: %d\n", numFixit); 78 | for (auto j = 0U; j < numFixit; j++) { 79 | CXString fixit = clang_getDiagnosticFixIt(diag, j, NULL); 80 | printf(" Fixit: %s\n", clang_getCString(fixit)); 81 | clang_disposeString(fixit); 82 | } 83 | } 84 | 85 | void show_diagnosis_child(const CXDiagnostic &diag) { 86 | CXDiagnosticSet childDiagSet = clang_getChildDiagnostics(diag); 87 | unsigned numChildDiag = clang_getNumDiagnosticsInSet(childDiagSet); 88 | printf(" NumChildDiag: %d\n", numChildDiag); 89 | 90 | // TODO: show child DiagnosticSet recursively(?) 91 | } 92 | 93 | void diagnosis(const CXTranslationUnit &tu) { 94 | CXDiagnosticSet diagSet = clang_getDiagnosticSetFromTU(tu); 95 | unsigned numDiag = clang_getNumDiagnosticsInSet(diagSet); 96 | printf("numDiag: %d\n", numDiag); 97 | 98 | for (auto i = 0U; i < numDiag; i++) { 99 | CXDiagnostic diag = clang_getDiagnosticInSet(diagSet, i); 100 | 101 | // show diagnosis spell 102 | CXString diagText = clang_getDiagnosticSpelling(diag); 103 | printf(" Diagnosis: %s\n", clang_getCString(diagText)); 104 | clang_disposeString(diagText); 105 | 106 | show_diagnosis_format(diag); // format 107 | show_diagnosis_severity(diag); // severity 108 | show_diagnosis_location(diag); // location 109 | show_diagnosis_category(diag); // category 110 | show_diagnosis_range(diag); // range 111 | show_diagnosis_fixit(diag); // fixit 112 | show_diagnosis_child(diag); // child 113 | printf("\n"); 114 | 115 | clang_disposeDiagnostic(diag); 116 | } 117 | clang_disposeDiagnosticSet(diagSet); 118 | } 119 | 120 | int main(int argc, char **argv) { 121 | if (argc < 2) { 122 | printf("Diagnosis filename [options ...]\n"); 123 | exit(1); 124 | } 125 | 126 | const auto filename = argv[1]; 127 | const auto cmdArgs = &argv[2]; 128 | auto numArgs = argc - 2; 129 | 130 | // create index w/ excludeDeclsFromPCH = 1, displayDiagnostics=1. 131 | CXIndex index = clang_createIndex(1, 0); 132 | 133 | // create Translation Unit 134 | CXTranslationUnit tu = clang_parseTranslationUnit(index, filename, cmdArgs, numArgs, 135 | NULL, 0, 0); 136 | if (tu == NULL) { 137 | printf("Cannot parse translation unit\n"); 138 | return 1; 139 | } 140 | 141 | // show diagnosis 142 | diagnosis(tu); 143 | 144 | clang_disposeTranslationUnit(tu); 145 | clang_disposeIndex(index); 146 | return 0; 147 | } 148 | -------------------------------------------------------------------------------- /Diagnosis/Makefile: -------------------------------------------------------------------------------- 1 | 2 | UNAME_S:=$(shell uname -s) 3 | 4 | TARGET=Diagnosis 5 | CXX=clang 6 | CFLAGS=-std=c++11 -O2 -Wall -Wextra 7 | ifeq ($(UNAME_S), Darwin) 8 | CLANG_STDLIB:=-stdlib=libstdc++ 9 | CFLAGS+=$(CLANG_STDLIB) 10 | endif 11 | FLAGS=`llvm-config --cxxflags --ldflags` -lclang $(CFLAGS) 12 | 13 | SAMPLE_DIR=samples 14 | SAMPLES:=$(wildcard $(SAMPLE_DIR)/*.cc) 15 | SAMPLES_OUT:=$(subst .cc,_out.txt,$(SAMPLES)) 16 | 17 | all: $(TARGET) 18 | 19 | $(TARGET): $(TARGET).cc 20 | $(CXX) $(TARGET).cc -o $(TARGET) $(FLAGS) 21 | 22 | run: $(SAMPLES_OUT) 23 | 24 | $(SAMPLE_DIR)/%_out.txt: $(TARGET) $(SAMPLE_DIR)/%.cc 25 | ./$(TARGET) $(SAMPLE_DIR)/$*.cc `llvm-config --cxxflags` $(CLANG_STDLIB) > $@ 2>&1 26 | 27 | clean: 28 | @find . -name '*~' | xargs rm -f 29 | @rm -f $(TARGET) $(SAMPLES_OUT) 30 | 31 | .PHONY: check-syntax 32 | check-syntax: 33 | @$(CXX) -c $(CHK_SOURCES) -fsyntax-only $(FLAGS) 34 | -------------------------------------------------------------------------------- /Diagnosis/samples/sample1.cc: -------------------------------------------------------------------------------- 1 | #include 2 | int main(void) { 3 | std::vectr v; 4 | } 5 | -------------------------------------------------------------------------------- /Diagnosis/samples/sample2.cc: -------------------------------------------------------------------------------- 1 | #include "sample.h" 2 | typedef int sampleInt; 3 | 4 | class C { 5 | void f(); 6 | }; 7 | 8 | void C::f() { } 9 | 10 | void hoge() { 11 | sampleInt a = 10; 12 | C c; 13 | c.f(); 14 | } 15 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Masahiro Sano 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libclang-sample 2 | 3 | LibClang sample programs. 4 | 5 | ## Samples 6 | 7 | - Token 8 | - AST(abstruct syntax tree) 9 | - Compilation Database 10 | - Code Completion 11 | - Diagnosis 12 | 13 | ## Copyright 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
AuthorMasahiro Sano
CopyrightCopyright (c) 2014- Masahiro Sano
LicenseMIT License
26 | 27 | -------------------------------------------------------------------------------- /Token/Makefile: -------------------------------------------------------------------------------- 1 | 2 | UNAME_S:=$(shell uname -s) 3 | 4 | TARGET=Tokenize 5 | CXX=clang 6 | CFLAGS=-std=c++11 -O2 -Wall -Wextra 7 | ifeq ($(UNAME_S), Darwin) 8 | CFLAGS+=-stdlib=libstdc++ 9 | endif 10 | FLAGS=`llvm-config --cxxflags --ldflags` -lclang $(CFLAGS) 11 | 12 | SAMPLE_DIR=samples 13 | SAMPLES:=$(wildcard $(SAMPLE_DIR)/*.cc) 14 | SAMPLES_OUT:=$(subst .cc,_out.txt,$(SAMPLES)) 15 | 16 | all: $(TARGET) 17 | 18 | $(TARGET): $(TARGET).cc 19 | $(CXX) $(TARGET).cc -o $(TARGET) $(FLAGS) 20 | 21 | run: $(SAMPLES_OUT) 22 | 23 | $(SAMPLE_DIR)/%_out.txt: $(TARGET) $(SAMPLE_DIR)/%.cc 24 | ./$(TARGET) $(SAMPLE_DIR)/$*.cc `llvm-config --cxxflags` > $@ 2>&1 25 | 26 | clean: 27 | @find . -name '*~' | xargs rm -f 28 | @rm -f $(TARGET) $(SAMPLES_OUT) 29 | 30 | .PHONY: check-syntax 31 | check-syntax: 32 | @$(CXX) -c $(CHK_SOURCES) -fsyntax-only $(FLAGS) 33 | -------------------------------------------------------------------------------- /Token/Tokenize.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | const char *_getTokenKindSpelling(CXTokenKind kind) { 6 | switch (kind) { 7 | case CXToken_Punctuation: return "Punctuation"; break; 8 | case CXToken_Keyword: return "Keyword"; break; 9 | case CXToken_Identifier: return "Identifier"; break; 10 | case CXToken_Literal: return "Literal"; break; 11 | case CXToken_Comment: return "Comment"; break; 12 | default: return "Unknown"; break; 13 | } 14 | } 15 | 16 | void show_all_tokens(const CXTranslationUnit &tu, const CXToken *tokens, unsigned numTokens) { 17 | printf("=== show tokens ===\n"); 18 | printf("NumTokens: %d\n", numTokens); 19 | for (auto i = 0U; i < numTokens; i++) { 20 | const CXToken &token = tokens[i]; 21 | CXTokenKind kind = clang_getTokenKind(token); 22 | CXString spell = clang_getTokenSpelling(tu, token); 23 | CXSourceLocation loc = clang_getTokenLocation(tu, token); 24 | 25 | CXFile file; 26 | unsigned line, column, offset; 27 | clang_getFileLocation(loc, &file, &line, &column, &offset); 28 | CXString fileName = clang_getFileName(file); 29 | 30 | printf("Token: %d\n", i); 31 | printf(" Text: %s\n", clang_getCString(spell)); 32 | printf(" Kind: %s\n", _getTokenKindSpelling(kind)); 33 | printf(" Location: %s:%d:%d:%d\n", 34 | clang_getCString(fileName), line, column, offset); 35 | printf("\n"); 36 | 37 | clang_disposeString(fileName); 38 | clang_disposeString(spell); 39 | } 40 | } 41 | 42 | unsigned get_filesize(const char *fileName) { 43 | FILE *fp = fopen(fileName, "r"); 44 | fseek(fp, 0, SEEK_END); 45 | auto size = ftell(fp); 46 | fclose(fp); 47 | return size; 48 | } 49 | 50 | CXSourceRange get_filerange(const CXTranslationUnit &tu, const char *filename) { 51 | CXFile file = clang_getFile(tu, filename); 52 | auto fileSize = get_filesize(filename); 53 | 54 | // get top/last location of the file 55 | CXSourceLocation topLoc = clang_getLocationForOffset(tu, file, 0); 56 | CXSourceLocation lastLoc = clang_getLocationForOffset(tu, file, fileSize); 57 | if (clang_equalLocations(topLoc, clang_getNullLocation()) || 58 | clang_equalLocations(lastLoc, clang_getNullLocation()) ) { 59 | printf("cannot retrieve location\n"); 60 | exit(1); 61 | } 62 | 63 | // make a range from locations 64 | CXSourceRange range = clang_getRange(topLoc, lastLoc); 65 | if (clang_Range_isNull(range)) { 66 | printf("cannot retrieve range\n"); 67 | exit(1); 68 | } 69 | 70 | return range; 71 | } 72 | 73 | void show_clang_version(void) { 74 | CXString version = clang_getClangVersion(); 75 | printf("%s\n", clang_getCString(version)); 76 | clang_disposeString(version); 77 | } 78 | 79 | int main(int argc, char **argv) { 80 | if (argc < 2) { 81 | printf("Tokenize filename [options ...]\n"); 82 | exit(1); 83 | } 84 | 85 | show_clang_version(); 86 | 87 | const auto filename = argv[1]; 88 | const auto cmdArgs = &argv[2]; 89 | auto numArgs = argc - 2; 90 | 91 | // create index w/ excludeDeclsFromPCH = 1, displayDiagnostics=1. 92 | CXIndex index = clang_createIndex(1, 1); 93 | 94 | // create Translation Unit 95 | CXTranslationUnit tu = clang_parseTranslationUnit(index, filename, cmdArgs, numArgs, NULL, 0, 0); 96 | if (tu == NULL) { 97 | printf("Cannot parse translation unit\n"); 98 | return 1; 99 | } 100 | 101 | // get CXSouceRange of the file 102 | CXSourceRange range = get_filerange(tu, filename); 103 | 104 | // tokenize in the range 105 | CXToken *tokens; 106 | unsigned numTokens; 107 | clang_tokenize(tu, range, &tokens, &numTokens); 108 | 109 | // show tokens 110 | show_all_tokens(tu, tokens, numTokens); 111 | 112 | clang_disposeTokens(tu, tokens, numTokens); 113 | clang_disposeTranslationUnit(tu); 114 | clang_disposeIndex(index); 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /Token/samples/sample1.cc: -------------------------------------------------------------------------------- 1 | int main("aa", /* "bb"= */1 ) 2 | -------------------------------------------------------------------------------- /Token/samples/sample2.cc: -------------------------------------------------------------------------------- 1 | typedef int sampleInt; 2 | class C { 3 | void f(); 4 | }; 5 | 6 | void hoge() { 7 | sampleInt a = 10; 8 | C c; 9 | c.f(); 10 | } 11 | --------------------------------------------------------------------------------