From c4c929a6a79348bcedd4ad78683e42b432dd3a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 8 Jan 2020 16:36:51 +0100 Subject: [PATCH] Clang import: StringLiteral, funcdecl3, determine includes with clang -v --- lib/clangastdump.cpp | 30 +++++++++++++++++++++++++----- lib/cppcheck.cpp | 21 ++++++++++++++++++++- test/testclangastdump.cpp | 8 ++++++++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/lib/clangastdump.cpp b/lib/clangastdump.cpp index 18c15b4eb..e5800f23d 100644 --- a/lib/clangastdump.cpp +++ b/lib/clangastdump.cpp @@ -45,6 +45,7 @@ static const std::string NullStmt = "NullStmt"; static const std::string ParmVarDecl = "ParmVarDecl"; static const std::string RecordDecl = "RecordDecl"; static const std::string ReturnStmt = "ReturnStmt"; +static const std::string StringLiteral = "StringLiteral"; static const std::string TypedefDecl = "TypedefDecl"; static const std::string UnaryOperator = "UnaryOperator"; static const std::string VarDecl = "VarDecl"; @@ -171,6 +172,10 @@ namespace clangastdump { std::string clangastdump::AstNode::getSpelling() const { + if (mExtTokens.back() == "extern") + return mExtTokens[mExtTokens.size() - 3]; + if (mExtTokens[mExtTokens.size() - 2].compare(0,4,"col:") == 0) + return ""; return mExtTokens[mExtTokens.size() - 2]; } @@ -180,6 +185,10 @@ std::string clangastdump::AstNode::getType() const return unquote(mExtTokens[mExtTokens.size() - 2]); if (nodeType == DeclRefExpr) return unquote(mExtTokens.back()); + if (nodeType == FunctionDecl) + return unquote((mExtTokens.back() == "extern") ? + mExtTokens[mExtTokens.size() - 2] : + mExtTokens.back()); if (nodeType == IntegerLiteral) return unquote(mExtTokens[mExtTokens.size() - 2]); if (nodeType == TypedefDecl) @@ -362,8 +371,13 @@ Token *clangastdump::AstNode::createTokens(TokenList *tokenList) } if (nodeType == FunctionDecl) { SymbolDatabase *symbolDatabase = mData->mSymbolDatabase; - addTypeTokens(tokenList, mExtTokens.back()); - Token *nameToken = addtoken(tokenList, mExtTokens[mExtTokens.size() - 2]); + std::string name, rettype; + const int nameIndex = (mExtTokens.back() == "extern") ? + (mExtTokens.size() - 3) : + (mExtTokens.size() - 2); + const int retTypeIndex = nameIndex + 1; + addTypeTokens(tokenList, mExtTokens[retTypeIndex]); + Token *nameToken = addtoken(tokenList, mExtTokens[nameIndex]); Scope *nestedIn = const_cast(nameToken->scope()); symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nestedIn)); Scope &scope = symbolDatabase->scopeList.back(); @@ -442,9 +456,13 @@ Token *clangastdump::AstNode::createTokens(TokenList *tokenList) const std::string &recordName = getSpelling(); if (!recordName.empty()) addtoken(tokenList, getSpelling()); - Scope *recordScope = createScope(tokenList, Scope::ScopeType::eStruct, children); - mData->mSymbolDatabase->typeList.push_back(Type(classDef, recordScope, classDef->scope())); - recordScope->definedType = &mData->mSymbolDatabase->typeList.back(); + if (children.empty()) + addtoken(tokenList, ";"); + else { + Scope *recordScope = createScope(tokenList, Scope::ScopeType::eStruct, children); + mData->mSymbolDatabase->typeList.push_back(Type(classDef, recordScope, classDef->scope())); + recordScope->definedType = &mData->mSymbolDatabase->typeList.back(); + } return nullptr; } if (nodeType == ReturnStmt) { @@ -453,6 +471,8 @@ Token *clangastdump::AstNode::createTokens(TokenList *tokenList) tok1->astOperand1(children[0]->createTokens(tokenList)); return tok1; } + if (nodeType == StringLiteral) + return addtoken(tokenList, mExtTokens.back()); if (nodeType == TypedefDecl) { addtoken(tokenList, "typedef"); addTypeTokens(tokenList, getType()); diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index e1740736c..61a287457 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -243,7 +243,26 @@ unsigned int CppCheck::check(const std::string &path) { if (mSettings.clang) { /* Experimental: import clang ast dump */ - const std::string cmd = "clang -cc1 -ast-dump " + path; + const std::string cmd1 = "clang -v -fsyntax-only " + path + " 2>&1"; + const std::pair res1 = executeCommand(cmd1); + if (!res1.first) { + std::cerr << "Failed to execute '" + cmd1 + "'" << std::endl; + return 0; + } + std::istringstream details(res1.second); + std::string line; + std::string includes; + while (std::getline(details, line)) { + if (line.find(" -internal-isystem ") == std::string::npos) + continue; + const std::vector options = split(line, " "); + for (int i = 0; i+1 < options.size(); i++) { + if (endsWith(options[i], "-isystem", 8)) + includes += options[i] + " " + options[i+1] + " "; + } + } + + const std::string cmd = "clang -cc1 -ast-dump " + includes + path; std::pair res = executeCommand(cmd); if (!res.first) { std::cerr << "Failed to execute '" + cmd + "'" << std::endl; diff --git a/test/testclangastdump.cpp b/test/testclangastdump.cpp index 89c2ddb36..1e6365d90 100644 --- a/test/testclangastdump.cpp +++ b/test/testclangastdump.cpp @@ -34,6 +34,7 @@ private: TEST_CASE(forStmt); TEST_CASE(funcdecl1); TEST_CASE(funcdecl2); + TEST_CASE(funcdecl3); TEST_CASE(ifelse); TEST_CASE(memberExpr); TEST_CASE(recordDecl); @@ -116,6 +117,13 @@ private: "return x@1 / y@2 ; }", parse(clang)); } + void funcdecl3() { + const char clang[] = "|-FunctionDecl 0x27cb6b8 col:12 __overflow 'int (FILE *, int)' extern\n" + "| |-ParmVarDecl 0x27cb528 col:30 'FILE *'\n" + "| `-ParmVarDecl 0x27cb5a0 col:35 'int'"; + ASSERT_EQUALS("int __overflow ( FILE * , int ) ;", parse(clang)); + } + void ifelse() { const char clang[] = "`-FunctionDecl 0x2637ba8 <1.c:1:1, line:4:1> line:1:5 foo 'int (int)'\n" " |-ParmVarDecl 0x2637ae0 col:13 used x 'int'\n"