参考书:《Getting Started with LLVM Core Libraries》
这一节主要是介绍clang的错误诊断。
一、编写makefile
延用第二节的makefile,新增libclang库的支持,不用多说,看第二节的详细解释,
这里贴代码,路径还是根据自己电脑路径更改:
LLVM_CONFIG ?= /Users/qinyao/LLVM/LLVM-9.0.0/build-release/bin/llvm-config
# CXX = /Users/qinyao/LLVM/LLVM-9.0.0/build-release/bin/clang++
CXXINCLUDE+=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1
# CXXINCLUDE+=/Users/qinyao/LLVM/LLVM-9.0.0/build-release/include/c++/v1
ISYSROOT+=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk
LIB+=/Users/qinyao/LLVM/LLVM-9.0.0/build-release/lib
ifndef VERBOSE
QUIET:=@
endif
SRC_DIR?=$(PWD)
LDFLAGS+=$(shell $(LLVM_CONFIG) --ldflags)
COMMON_FLAGS=-Wall -Wextra -I$(CXXINCLUDE) -isysroot $(ISYSROOT)
CXXFLAGS+=$(COMMON_FLAGS) $(shell $(LLVM_CONFIG) --cxxflags)
CPPFLAGS+=$(shell $(LLVM_CONFIG) --cppflags) -I$(SRC_DIR)
CLANGLIBS = \
-Wl\
-lclang\
-lclangFrontend\
-lclangDriver\
-lclangSerialization\
-lclangParse\
-lclangSema\
-lclangAnalysis\
-lclangEdit\
-lclangAST\
-lclangLex\
-lclangBasic
LLVMLIBS=$(shell $(LLVM_CONFIG) --libs)
PROJECT=uselibclang
PROJECT_OBJECTS=uselibclang.o
default: $(PROJECT)
%.o : $(SRC_DIR)/%.cpp
@echo Compiling $*.cpp
$(QUIET)$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $< -I/Users/qinyao/LLVM/LLVM-9.0.0/llvm-9.0.0.src/tools/clang/include
$(PROJECT) : $(PROJECT_OBJECTS)
@echo Linking $@
$(QUIET)$(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) $^ $(CLANGLIBS) $(LLVMLIBS) `$(LLVM_CONFIG) --system-libs`
clean::
$(QUIET)rm -f $(PROJECT) $(PROJECT_OBJECTS)
二、编写cpp代码
代码如下:
extern "C" {
#include "clang-c/Index.h"
}
#include "llvm/Support/CommandLine.h"
#include <iostream>
using namespace llvm;
static cl::opt<std::string> FileName(cl::Positional, cl::desc("Input file"), cl::Required);
int main(int argc, char** argv)
{
cl::ParseCommandLineOptions(argc, argv, "Diagnostics Example");
CXIndex index = clang_createIndex(0, 0);
const char *args[] = { "-I/usr/include","-I." };
CXTranslationUnit translationUnit = clang_parseTranslationUnit(index, FileName.c_str(), args, 2, NULL, 0,CXTranslationUnit_None);
unsigned diagnosticCount = clang_getNumDiagnostics(translationUnit);
for (unsigned i = 0; i < diagnosticCount; ++i) {
CXDiagnostic diagnostic = clang_getDiagnostic(translationUnit, i);
CXString category = clang_getDiagnosticCategoryText(diagnostic);
CXString message = clang_getDiagnosticSpelling(diagnostic);
unsigned severity = clang_getDiagnosticSeverity(diagnostic);
CXSourceLocation loc = clang_getDiagnosticLocation(diagnostic);
CXString fName;
unsigned line = 0, col = 0;
clang_getPresumedLocation(loc, &fName, &line, &col);
std::cout << "Severity: " << severity << " File: "
<< clang_getCString(fName) << " Line: "
<< line << " Col: " << col << " Category: \""
<< clang_getCString(category) << "\" Message: "
<< clang_getCString(message) << std::endl;
clang_disposeString(fName);
clang_disposeString(message);
clang_disposeString(category);
clang_disposeDiagnostic(diagnostic);
}
clang_disposeTranslationUnit(translationUnit);
clang_disposeIndex(index);
return 0;
}
解释:
- 导入c头文件,第一行要用c的方式编译
- clang_createIndex(0, 0) 函数,关闭原来的诊断,我们自己做,(贴上原来的解释好像比较清楚):
It receives two integer-encoded Booleans as parameters: the first is true if we want to exclude declarations from precompiled headers (PCH) and the second is true if we want to display diagnostics. We set
both to false (zero) because we want to display the diagnostics by ourselves. - clang_parseTranslationUnit函数,拿到翻译单元
It receives as an argument the name of the source file to parse, which we retrieve from the FileName global. This variable corresponds to the string parameter used to launch our tool. We also need to specify a set of two arguments defining where to find include files—you are free to adjust these arguments to suit your system. - 往下的大致就是从拿到的翻译单元中获取各种信息,最后打印出来。
三、编译执行
-
可以先看一下编译参数 make -Bn:
image.png -
可以看到诊断结果,hello.c 是包含错误写法的一段简单的代码.
image.png
网友评论