Index namespace alias and MSVC __interface; add --enable-assert to waf; add lexical container to xref requests

This commit is contained in:
Fangrui Song 2018-02-20 20:26:17 -08:00
parent 909c2e247a
commit 1a4da727da
14 changed files with 156 additions and 205 deletions

View File

@ -23,7 +23,6 @@
#include "serializer.h"
#include "serializers/json.h"
#include "test.h"
#include "threaded_queue.h"
#include "timer.h"
#include "timestamp_manager.h"
#include "work_thread.h"

View File

@ -162,13 +162,13 @@ struct Config {
};
Completion completion;
// Maximum number of definition/reference/... results.
int maxXrefResults = 500;
struct Extension {
// If true, reference results will include "containerName".
bool referenceContainer = false;
struct Xref {
// If true, |Location[]| response will include lexical container.
bool container = false;
// Maximum number of definition/reference/... results.
int maxNum = 300;
};
Extension extension;
Xref xref;
struct Index {
// 0: none, 1: doxygen, 2: all comments
@ -195,7 +195,7 @@ struct Config {
};
MAKE_REFLECT_STRUCT(Config::ClientCapability, snippetSupport);
MAKE_REFLECT_STRUCT(Config::Completion, filterAndSort, detailedLabel);
MAKE_REFLECT_STRUCT(Config::Extension, referenceContainer);
MAKE_REFLECT_STRUCT(Config::Xref, container, maxNum);
MAKE_REFLECT_STRUCT(Config::Index, comments, attributeMakeCallsToCtor);
MAKE_REFLECT_STRUCT(Config,
compilationDatabaseCommand,
@ -233,8 +233,7 @@ MAKE_REFLECT_STRUCT(Config,
client,
completion,
maxXrefResults,
extension,
xref,
index,
dumpAST);

View File

@ -1510,20 +1510,24 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
ClangCursor lex_parent(fromContainer(decl->lexicalContainer));
SetUsePreflight(db, sem_parent);
SetUsePreflight(db, lex_parent);
ClangCursor cursor = decl->cursor;
switch (decl->entityInfo->kind) {
case CXIdxEntity_Unexposed:
LOG_S(INFO) << "CXIdxEntity_Unexposed " << cursor.get_spell_name();
break;
case CXIdxEntity_CXXNamespace: {
ClangCursor decl_cursor = decl->cursor;
Range spell = decl_cursor.get_spell();
Range spell = cursor.get_spell();
IndexTypeId ns_id = db->ToTypeId(HashUsr(decl->entityInfo->USR));
IndexType* ns = db->Resolve(ns_id);
ns->def.kind = GetSymbolKind(decl->entityInfo->kind);
if (ns->def.detailed_name.empty()) {
SetTypeName(ns, decl_cursor, decl->semanticContainer,
SetTypeName(ns, cursor, decl->semanticContainer,
decl->entityInfo->name, param);
ns->def.spell = SetUse(db, spell, sem_parent, Role::Definition);
ns->def.extent =
SetUse(db, decl_cursor.get_extent(), lex_parent, Role::None);
SetUse(db, cursor.get_extent(), lex_parent, Role::None);
if (decl->semanticContainer) {
IndexTypeId parent_id = db->ToTypeId(
ClangCursor(decl->semanticContainer->cursor).get_usr_hash());
@ -1537,6 +1541,10 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
break;
}
case CXIdxEntity_CXXNamespaceAlias:
assert(false && "CXXNamespaceAlias");
break;
case CXIdxEntity_ObjCProperty:
case CXIdxEntity_ObjCIvar:
case CXIdxEntity_EnumConstant:
@ -1804,6 +1812,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
case CXIdxEntity_Enum:
case CXIdxEntity_Union:
case CXIdxEntity_Struct:
case CXIdxEntity_CXXInterface:
case CXIdxEntity_CXXClass: {
ClangCursor decl_cursor = decl->cursor;
Range spell = decl_cursor.get_spell();
@ -1919,30 +1928,6 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
}
break;
}
default:
std::cerr
<< "!! Unhandled indexDeclaration: "
<< ClangCursor(decl->cursor).ToString() << " at "
<< ClangCursor(decl->cursor).get_spell().start.ToString()
<< std::endl;
std::cerr << " entityInfo->kind = " << decl->entityInfo->kind
<< std::endl;
std::cerr << " entityInfo->USR = " << decl->entityInfo->USR
<< std::endl;
if (decl->declAsContainer)
std::cerr << " declAsContainer = "
<< ClangCursor(decl->declAsContainer->cursor).ToString()
<< std::endl;
if (decl->semanticContainer)
std::cerr << " semanticContainer = "
<< ClangCursor(decl->semanticContainer->cursor).ToString()
<< std::endl;
if (decl->lexicalContainer)
std::cerr << " lexicalContainer = "
<< ClangCursor(decl->lexicalContainer->cursor).get_usr_hash()
<< std::endl;
break;
}
}
@ -1990,17 +1975,38 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
ClangCursor cursor(ref->cursor);
ClangCursor lex_parent(fromContainer(ref->container));
ClangCursor referenced;
if (ref->referencedEntity)
referenced = ref->referencedEntity->cursor;
SetUsePreflight(db, lex_parent);
switch (ref->referencedEntity->kind) {
case CXIdxEntity_CXXNamespaceAlias:
case CXIdxEntity_Unexposed:
LOG_S(INFO) << "CXIdxEntity_Unexposed " << cursor.get_spell_name();
break;
case CXIdxEntity_CXXNamespace: {
ClangCursor referenced = ref->referencedEntity->cursor;
IndexType* ns = db->Resolve(db->ToTypeId(referenced.get_usr_hash()));
AddUse(db, ns->uses, cursor.get_spell(), fromContainer(ref->container));
break;
}
case CXIdxEntity_CXXNamespaceAlias: {
IndexType* ns = db->Resolve(db->ToTypeId(referenced.get_usr_hash()));
AddUse(db, ns->uses, cursor.get_spell(), fromContainer(ref->container));
if (!ns->def.spell) {
ClangCursor sem_parent = referenced.get_semantic_parent();
ClangCursor lex_parent = referenced.get_lexical_parent();
SetUsePreflight(db, sem_parent);
SetUsePreflight(db, lex_parent);
ns->def.spell = SetUse(db, referenced.get_spell(), sem_parent, Role::Definition);
ns->def.extent = SetUse(db, referenced.get_extent(), lex_parent, Role::None);
std::string name = referenced.get_spell_name();
SetTypeName(ns, referenced, nullptr, name.c_str(), param);
}
break;
}
case CXIdxEntity_ObjCProperty:
case CXIdxEntity_ObjCIvar:
case CXIdxEntity_EnumConstant:
@ -2146,6 +2152,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
case CXIdxEntity_ObjCProtocol:
case CXIdxEntity_ObjCClass:
case CXIdxEntity_Typedef:
case CXIdxEntity_CXXInterface: // MSVC __interface
case CXIdxEntity_CXXTypeAlias:
case CXIdxEntity_Enum:
case CXIdxEntity_Union:
@ -2176,36 +2183,6 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
UniqueAddUseSpell(db, ref_type->uses, ref->cursor);
break;
}
default:
std::cerr
<< "!! Unhandled indexEntityReference: " << cursor.ToString()
<< " at "
<< ClangCursor(ref->cursor).get_spell().start.ToString()
<< std::endl;
std::cerr << " ref->referencedEntity->kind = "
<< ref->referencedEntity->kind << std::endl;
if (ref->parentEntity)
std::cerr << " ref->parentEntity->kind = "
<< ref->parentEntity->kind << std::endl;
std::cerr
<< " ref->loc = "
<< ClangCursor(ref->cursor).get_spell().start.ToString()
<< std::endl;
std::cerr << " ref->kind = " << ref->kind << std::endl;
if (ref->parentEntity)
std::cerr << " parentEntity = "
<< ClangCursor(ref->parentEntity->cursor).ToString()
<< std::endl;
if (ref->referencedEntity)
std::cerr << " referencedEntity = "
<< ClangCursor(ref->referencedEntity->cursor).ToString()
<< std::endl;
if (ref->container)
std::cerr << " container = "
<< ClangCursor(ref->container->cursor).ToString()
<< std::endl;
break;
}
}

View File

@ -638,6 +638,6 @@ MAKE_REFLECT_STRUCT(Out_CquerySetInactiveRegion, jsonrpc, method, params);
struct Out_LocationList : public lsOutMessage<Out_LocationList> {
lsRequestId id;
std::vector<lsLocation> result;
std::vector<lsLocationEx> result;
};
MAKE_REFLECT_STRUCT(Out_LocationList, jsonrpc, id, result);

View File

@ -27,13 +27,15 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> {
FindSymbolsAtLocation(working_file, file, request->params.position)) {
if (sym.kind == SymbolKind::Type) {
if (const auto* def = db->GetType(sym).AnyDef())
out.result = GetLsLocations(db, working_files,
ToUses(db, def->parents), config->maxXrefResults);
out.result =
GetLsLocationExs(db, working_files, ToUses(db, def->parents),
config->xref.container, config->xref.maxNum);
break;
} else if (sym.kind == SymbolKind::Func) {
if (const auto* def = db->GetFunc(sym).AnyDef())
out.result = GetLsLocations(db, working_files, ToUses(db, def->base),
config->maxXrefResults);
out.result =
GetLsLocationExs(db, working_files, ToUses(db, def->base),
config->xref.container, config->xref.maxNum);
break;
}
}

View File

@ -32,7 +32,9 @@ struct CqueryCallersHandler : BaseMessageHandler<Ipc_CqueryCallers> {
uses.push_back(func_ref);
for (Use func_ref : GetCallersForAllDerivedFunctions(db, func))
uses.push_back(func_ref);
out.result = GetLsLocations(db, working_files, uses, config->maxXrefResults);
out.result =
GetLsLocationExs(db, working_files, uses, config->xref.container,
config->xref.maxNum);
break;
}
}

View File

@ -27,13 +27,14 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> {
FindSymbolsAtLocation(working_file, file, request->params.position)) {
if (sym.kind == SymbolKind::Type) {
QueryType& type = db->GetType(sym);
out.result = GetLsLocations(db, working_files, ToUses(db, type.derived),
config->maxXrefResults);
out.result =
GetLsLocationExs(db, working_files, ToUses(db, type.derived),
config->xref.container, config->xref.maxNum);
break;
} else if (sym.kind == SymbolKind::Func) {
QueryFunc& func = db->GetFunc(sym);
out.result = GetLsLocations(db, working_files, ToUses(db, func.derived),
config->maxXrefResults);
out.result = GetLsLocationExs(db, working_files, ToUses(db, func.derived),
config->xref.container, config->xref.maxNum);
break;
}
}

View File

@ -101,7 +101,7 @@ struct CqueryRandomHandler : BaseMessageHandler<Ipc_CqueryRandom> {
}
std::vector<double> x(n, 1), y;
for (int j = 0; j < 30; j++) {
for (int j = 0; j < 8; j++) {
y.assign(n, kDamping);
for (int i = 0; i < n; i++)
for (auto& it : adj[i])
@ -124,8 +124,8 @@ struct CqueryRandomHandler : BaseMessageHandler<Ipc_CqueryRandom> {
Maybe<Use> use = GetDefinitionExtentOfSymbol(db, syms[i]);
if (!use)
continue;
optional<lsLocation> ls_loc = GetLsLocation(db, working_files, *use);
if (ls_loc)
if (auto ls_loc = GetLsLocationEx(db, working_files, *use,
config->xref.container))
out.result.push_back(*ls_loc);
break;
}

View File

@ -39,8 +39,8 @@ struct CqueryVarsHandler : BaseMessageHandler<Ipc_CqueryVars> {
case SymbolKind::Type: {
QueryType& type = db->types[id.id];
out.result =
GetLsLocations(db, working_files, ToUses(db, type.instances),
config->maxXrefResults);
GetLsLocationExs(db, working_files, ToUses(db, type.instances),
config->xref.container, config->xref.maxNum);
break;
}
}

View File

@ -1,4 +1,3 @@
#include "fuzzy_match.h"
#include "lex_utils.h"
#include "message_handler.h"
#include "query_utils.h"
@ -21,18 +20,17 @@ REGISTER_IPC_MESSAGE(Ipc_TextDocumentDefinition);
struct Out_TextDocumentDefinition
: public lsOutMessage<Out_TextDocumentDefinition> {
lsRequestId id;
std::vector<lsLocation> result;
std::vector<lsLocationEx> result;
};
MAKE_REFLECT_STRUCT(Out_TextDocumentDefinition, jsonrpc, id, result);
std::vector<Use> GetGotoDefinitionTargets(QueryDatabase* db,
SymbolRef sym) {
switch (sym.kind) {
// Returns GetDeclarationsOfSymbolForGotoDefinition and
// variable type definition.
case SymbolKind::Var: {
std::vector<Use> ret =
GetDeclarationsOfSymbolForGotoDefinition(db, sym);
// If there is no declaration, jump the its type.
if (ret.empty()) {
for (auto& def : db->GetVar(sym).def)
if (def.type) {
@ -67,6 +65,7 @@ struct TextDocumentDefinitionHandler
Out_TextDocumentDefinition out;
out.id = request->id;
Maybe<Use> on_def;
bool has_symbol = false;
int target_line = request->params.position.line;
int target_column = request->params.position.character;
@ -87,6 +86,7 @@ struct TextDocumentDefinitionHandler
// If on a definition, clear |uses| to find declarations below.
if (spell.file == file_id &&
spell.range.Contains(target_line, target_column)) {
on_def = spell;
uses.clear();
return false;
}
@ -99,10 +99,16 @@ struct TextDocumentDefinitionHandler
return true;
});
if (uses.empty())
if (uses.empty()) {
// The symbol has no definition or the cursor is on a definition.
uses = GetGotoDefinitionTargets(db, sym);
// There is no declaration but the cursor is on a definition.
if (uses.empty() && on_def)
uses.push_back(*on_def);
}
AddRange(&out.result,
GetLsLocations(db, working_files, uses, config->maxXrefResults));
GetLsLocationExs(db, working_files, uses, config->xref.container,
config->xref.maxNum));
if (!out.result.empty())
break;
}
@ -111,7 +117,7 @@ struct TextDocumentDefinitionHandler
if (out.result.empty()) {
for (const IndexInclude& include : file->def->includes) {
if (include.line == target_line) {
lsLocation result;
lsLocationEx result;
result.uri = lsDocumentUri::FromPath(include.resolved_path);
out.result.push_back(result);
has_symbol = true;
@ -154,8 +160,8 @@ struct TextDocumentDefinitionHandler
if (best_i != -1) {
Maybe<Use> use = GetDefinitionSpellingOfSymbol(db, db->symbols[best_i]);
assert(use);
optional<lsLocation> ls_loc = GetLsLocation(db, working_files, *use);
if (ls_loc)
if (auto ls_loc = GetLsLocationEx(db, working_files, *use,
config->xref.container))
out.result.push_back(*ls_loc);
}
}

View File

@ -56,9 +56,8 @@ struct TextDocumentReferencesHandler
// Found symbol. Return references.
EachUse(db, sym, request->params.context.includeDeclaration,
[&](Use use) {
if (optional<lsLocationEx> ls_loc =
GetLsLocationEx(db, working_files, use,
config->extension.referenceContainer))
if (optional<lsLocationEx> ls_loc = GetLsLocationEx(
db, working_files, use, config->xref.container))
out.result.push_back(*ls_loc);
});
break;

View File

@ -6,6 +6,7 @@
#include <climits>
#include <queue>
#include <stack>
#include <unordered_set>
namespace {
@ -118,25 +119,25 @@ std::vector<Use> GetDeclarationsOfSymbolForGotoDefinition(
bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) {
std::unordered_set<Usr> seen;
std::queue<QueryFunc*> queue;
std::stack<QueryFunc*> stack;
seen.insert(root.usr);
queue.push(&root);
while (!queue.empty()) {
QueryFunc& func = *queue.front();
queue.pop();
stack.push(&root);
while (!stack.empty()) {
QueryFunc& func = *stack.top();
stack.pop();
if (!func.uses.empty())
return true;
if (auto* def = func.AnyDef()) {
EachDefinedEntity(db->funcs, def->base, [&](QueryFunc& func1) {
if (!seen.count(func1.usr)) {
seen.insert(func1.usr);
queue.push(&func1);
stack.push(&func1);
}
});
EachDefinedEntity(db->funcs, func.derived, [&](QueryFunc& func1) {
if (!seen.count(func1.usr)) {
seen.insert(func1.usr);
queue.push(&func1);
stack.push(&func1);
}
});
}
@ -147,22 +148,20 @@ bool HasCallersOnSelfOrBaseOrDerived(QueryDatabase* db, QueryFunc& root) {
std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
QueryFunc& root) {
std::vector<Use> callers;
const QueryFunc::Def* def = root.AnyDef();
if (!def)
return callers;
std::queue<QueryFunc*> queue;
EachDefinedEntity(db->funcs, def->base, [&](QueryFunc& func1) {
queue.push(&func1);
});
while (!queue.empty()) {
QueryFunc& func = *queue.front();
queue.pop();
std::unordered_set<Usr> seen;
std::stack<QueryFunc*> stack;
seen.insert(root.usr);
stack.push(&root);
while (!stack.empty()) {
QueryFunc& func = *stack.top();
stack.pop();
AddRange(&callers, func.uses);
if (const QueryFunc::Def* def1 = func.AnyDef()) {
EachDefinedEntity(db->funcs, def1->base, [&](QueryFunc& func1) {
queue.push(&func1);
if (auto* def = func.AnyDef()) {
EachDefinedEntity(db->funcs, def->base, [&](QueryFunc& func1) {
if (!seen.count(func1.usr)) {
seen.insert(func1.usr);
stack.push(&func1);
}
});
}
}
@ -173,20 +172,20 @@ std::vector<Use> GetCallersForAllBaseFunctions(QueryDatabase* db,
std::vector<Use> GetCallersForAllDerivedFunctions(QueryDatabase* db,
QueryFunc& root) {
std::vector<Use> callers;
std::queue<QueryFunc*> queue;
EachDefinedEntity(db->funcs, root.derived, [&](QueryFunc& func) {
queue.push(&func);
});
while (!queue.empty()) {
QueryFunc& func = *queue.front();
queue.pop();
EachDefinedEntity(db->funcs, func.derived, [&](QueryFunc& func1) {
queue.push(&func1);
});
std::unordered_set<Usr> seen;
std::stack<QueryFunc*> stack;
seen.insert(root.usr);
stack.push(&root);
while (!stack.empty()) {
QueryFunc& func = *stack.top();
stack.pop();
AddRange(&callers, func.uses);
EachDefinedEntity(db->funcs, func.derived, [&](QueryFunc& func1) {
if (!seen.count(func1.usr)) {
seen.insert(func1.usr);
stack.push(&func1);
}
});
}
return callers;
@ -198,12 +197,10 @@ optional<lsPosition> GetLsPosition(WorkingFile* working_file,
return lsPosition(position.line, position.column);
int column = position.column;
optional<int> start =
working_file->GetBufferPosFromIndexPos(position.line, &column, false);
if (!start)
return nullopt;
return lsPosition(*start, column);
if (optional<int> start =
working_file->GetBufferPosFromIndexPos(position.line, &column, false))
return lsPosition(*start, column);
return nullopt;
}
optional<lsRange> GetLsRange(WorkingFile* working_file, const Range& location) {
@ -272,13 +269,13 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db,
optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
WorkingFiles* working_files,
Use use,
bool extension) {
bool container) {
optional<lsLocation> ls_loc = GetLsLocation(db, working_files, use);
if (!ls_loc)
return nullopt;
lsLocationEx ret;
ret.lsLocation::operator=(*ls_loc);
if (extension) {
if (container) {
EachEntityDef(db, use, [&](const auto& def) {
ret.containerName = std::string_view(def.detailed_name);
return false;
@ -287,17 +284,15 @@ optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
return ret;
}
std::vector<lsLocation> GetLsLocations(QueryDatabase* db,
WorkingFiles* working_files,
const std::vector<Use>& uses,
int limit) {
std::vector<lsLocation> ret;
for (Use use : uses) {
optional<lsLocation> location =
GetLsLocation(db, working_files, use);
if (location)
ret.push_back(*location);
}
std::vector<lsLocationEx> GetLsLocationExs(QueryDatabase* db,
WorkingFiles* working_files,
const std::vector<Use>& uses,
bool container,
int limit) {
std::vector<lsLocationEx> ret;
for (Use use : uses)
if (auto loc = GetLsLocationEx(db, working_files, use, container))
ret.push_back(*loc);
std::sort(ret.begin(), ret.end());
ret.erase(std::unique(ret.begin(), ret.end()), ret.end());
if (ret.size() > limit)
@ -311,6 +306,8 @@ optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
SymbolIdx sym,
bool use_short_name) {
switch (sym.kind) {
case SymbolKind::Invalid:
break;
case SymbolKind::File: {
QueryFile& file = db->GetFile(sym);
if (!file.def)
@ -321,51 +318,19 @@ optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
info.kind = lsSymbolKind::File;
return info;
}
case SymbolKind::Type: {
const QueryType::Def* def = db->GetType(sym).AnyDef();
if (!def)
break;
default: {
lsSymbolInformation info;
if (use_short_name)
info.name = def->ShortName();
else
info.name = def->detailed_name;
info.kind = def->kind;
if (def->detailed_name.c_str() != def->ShortName())
info.containerName = def->detailed_name;
EachEntityDef(db, sym, [&](const auto& def) {
if (use_short_name)
info.name = def.ShortName();
else
info.name = def.detailed_name;
info.kind = def.kind;
info.containerName = def.detailed_name;
return false;
});
return info;
}
case SymbolKind::Func: {
const QueryFunc::Def* def = db->GetFunc(sym).AnyDef();
if (!def)
break;
lsSymbolInformation info;
if (use_short_name)
info.name = def->ShortName();
else
info.name = def->detailed_name;
info.kind = def->kind;
info.containerName = def->detailed_name;
return info;
}
case SymbolKind::Var: {
const QueryVar::Def* def = db->GetVar(sym).AnyDef();
if (!def)
break;
lsSymbolInformation info;
if (use_short_name)
info.name = def->ShortName();
else
info.name = def->detailed_name;
info.kind = def->kind;
info.containerName = def->detailed_name;
return info;
}
case SymbolKind::Invalid:
break;
}
return nullopt;

View File

@ -41,11 +41,12 @@ optional<lsLocation> GetLsLocation(QueryDatabase* db,
optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
WorkingFiles* working_files,
Use use,
bool extension);
std::vector<lsLocation> GetLsLocations(QueryDatabase* db,
WorkingFiles* working_files,
const std::vector<Use>& refs,
int limit);
bool container);
std::vector<lsLocationEx> GetLsLocationExs(QueryDatabase* db,
WorkingFiles* working_files,
const std::vector<Use>& refs,
bool container,
int limit);
// Returns a symbol. The symbol will have *NOT* have a location assigned.
optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
WorkingFiles* working_files,

14
wscript
View File

@ -83,8 +83,7 @@ def patch_byte_in_libclang(filename, offset, old, new):
def options(opt):
opt.load('compiler_cxx')
grp = opt.add_option_group('Configuration options related to use of clang from the system (not recommended)')
grp.add_option('--use-system-clang', dest='use_system_clang', default=False, action='store_true',
help='deprecated. Please specify --llvm-config, e.g. /usr/bin/llvm-config llvm-config-6.0')
grp.add_option('--enable-assert', action='store_true')
grp.add_option('--use-clang-cxx', dest='use_clang_cxx', default=False, action='store_true',
help='use clang C++ API')
grp.add_option('--bundled-clang', dest='bundled_clang', default='5.0.1',
@ -188,6 +187,12 @@ def configure(ctx):
if 'release' in ctx.options.variant:
cxxflags.append('-O' if 'asan' in ctx.options.variant else '-O3')
if ctx.options.enable_assert is None:
if 'debug' in ctx.options.variant:
ctx.options.enable_assert = True
if not ctx.options.enable_assert:
ctx.define('NDEBUG', 1)
if ctx.env.CXX_NAME == 'clang' and 'debug' in ctx.options.variant:
cxxflags.append('-fno-limit-debug-info')
@ -208,11 +213,6 @@ def configure(ctx):
return 'lib' + lib
return lib
# TODO remove
if ctx.options.use_system_clang:
print((('!' * 50)+'\n')*3)
print('--use-system-clang is deprecated. Please specify --llvm-config, e.g. /usr/bin/llvm-config llvm-config-6.0')
# Do not use bundled clang+llvm
if ctx.options.llvm_config is not None or ctx.options.clang_prefix is not None:
if ctx.options.llvm_config is not None: