aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp35
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp67
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangparser.h9
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp18
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangutils.h12
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp7
-rw-r--r--sources/shiboken2/libshiboken/bindingmanager.cpp9
-rw-r--r--sources/shiboken2/libshiboken/bindingmanager.h2
-rw-r--r--sources/shiboken2/libshiboken/sbkstring.cpp6
9 files changed, 116 insertions, 49 deletions
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp
index 1eaa36540..263c0a0bb 100644
--- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp
@@ -114,16 +114,6 @@ static inline CodeModel::AccessPolicy accessPolicy(CX_CXXAccessSpecifier access)
return result;
}
-static void setFileName(const CXCursor &cursor, _CodeModelItem *item)
-{
- const SourceRange range = getCursorRange(cursor);
- if (!range.first.file.isEmpty()) { // Has been observed to be 0 for invalid locations
- item->setFileName(QDir::cleanPath(range.first.file));
- item->setStartPosition(int(range.first.line), int(range.first.column));
- item->setEndPosition(int(range.second.line), int(range.second.column));
- }
-}
-
static bool isSigned(CXTypeKind kind)
{
switch (kind) {
@@ -178,8 +168,8 @@ public:
bool addClass(const CXCursor &cursor, CodeModel::ClassType t);
FunctionModelItem createFunction(const CXCursor &cursor,
- CodeModel::FunctionType t = CodeModel::Normal) const;
- FunctionModelItem createMemberFunction(const CXCursor &cursor) const;
+ CodeModel::FunctionType t = CodeModel::Normal);
+ FunctionModelItem createMemberFunction(const CXCursor &cursor);
void qualifyConstructor(const CXCursor &cursor);
TypeInfo createTypeInfoHelper(const CXType &type) const; // uncashed
TypeInfo createTypeInfo(const CXType &type) const;
@@ -206,6 +196,8 @@ public:
bool visitHeader(const char *cFileName) const;
+ void setFileName(const CXCursor &cursor, _CodeModelItem *item);
+
BaseVisitor *m_baseVisitor;
CodeModel *m_model;
@@ -285,7 +277,7 @@ static inline ExceptionSpecification exceptionSpecificationFromClang(int ce)
}
FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor,
- CodeModel::FunctionType t) const
+ CodeModel::FunctionType t)
{
QString name = getCursorSpelling(cursor);
// Apply type fixes to "operator X &" -> "operator X&"
@@ -334,7 +326,7 @@ static inline CodeModel::FunctionType functionTypeFromCursor(const CXCursor &cur
return result;
}
-FunctionModelItem BuilderPrivate::createMemberFunction(const CXCursor &cursor) const
+FunctionModelItem BuilderPrivate::createMemberFunction(const CXCursor &cursor)
{
const CodeModel::FunctionType functionType =
m_currentFunctionType == CodeModel::Signal || m_currentFunctionType == CodeModel::Slot
@@ -725,6 +717,17 @@ void BuilderPrivate::qualifyTypeDef(const CXCursor &typeRefCursor, const QShared
}
}
+void BuilderPrivate::setFileName(const CXCursor &cursor, _CodeModelItem *item)
+{
+ const SourceRange range = getCursorRange(cursor);
+ QString file = m_baseVisitor->getFileName(range.first.file);
+ if (!file.isEmpty()) { // Has been observed to be 0 for invalid locations
+ item->setFileName(QDir::cleanPath(file));
+ item->setStartPosition(int(range.first.line), int(range.first.column));
+ item->setEndPosition(int(range.second.line), int(range.second.column));
+ }
+}
+
Builder::Builder()
{
d = new BuilderPrivate(this);
@@ -937,7 +940,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
kind = EnumClass;
}
d->m_currentEnum.reset(new _EnumModelItem(d->m_model, name));
- setFileName(cursor, d->m_currentEnum.data());
+ d->setFileName(cursor, d->m_currentEnum.data());
d->m_currentEnum->setScope(d->m_scope);
d->m_currentEnum->setEnumKind(kind);
d->m_currentEnum->setSigned(isSigned(clang_getEnumDeclIntegerType(cursor).kind));
@@ -1024,7 +1027,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
// in subsequent modules.
NamespaceModelItem namespaceItem = parentNamespaceItem->findNamespace(name);
namespaceItem.reset(new _NamespaceModelItem(d->m_model, name));
- setFileName(cursor, namespaceItem.data());
+ d->setFileName(cursor, namespaceItem.data());
namespaceItem->setScope(d->m_scope);
namespaceItem->setType(type);
parentNamespaceItem->addNamespace(namespaceItem);
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp
index 6303d09e5..d0c5bc1b8 100644
--- a/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp
@@ -40,19 +40,49 @@
namespace clang {
-SourceFileCache::Snippet SourceFileCache::getCodeSnippet(const CXCursor &cursor)
+QString SourceFileCache::getFileName(CXFile file)
+{
+ auto it = m_fileNameCache.find(file);
+ if (it == m_fileNameCache.end())
+ it = m_fileNameCache.insert(file, clang::getFileName(file));
+ return it.value();
+}
+
+SourceFileCache::Snippet SourceFileCache::getCodeSnippet(const CXCursor &cursor,
+ QString *errorMessage)
{
Snippet result(nullptr, nullptr);
+
+ if (errorMessage)
+ errorMessage->clear();
+
const SourceRange range = getCursorRange(cursor);
- if (range.first.file.isEmpty() || range.second.file != range.first.file)
+ // Quick check for equal locations: Frequently happens if the code is
+ // the result of a macro expansion
+ if (range.first == range.second)
+ return result;
+
+ if (range.first.file != range.second.file) {
+ if (errorMessage)
+ *errorMessage = QStringLiteral("Range spans several files");
return result;
- FileBufferCache::Iterator it = m_fileBufferCache.find(range.first.file);
+ }
+
+ auto it = m_fileBufferCache.find(range.first.file);
if (it == m_fileBufferCache.end()) {
- QFile file(range.first.file);
+ const QString fileName = getFileName(range.first.file);
+ if (fileName.isEmpty()) {
+ if (errorMessage)
+ *errorMessage = QStringLiteral("Range has no file");
+ return result;
+ }
+ QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
- qWarning().noquote().nospace()
- << "Can't open " << QDir::toNativeSeparators(range.first.file)
- << ": " << file.errorString();
+ if (errorMessage) {
+ QTextStream str(errorMessage);
+ str << "Cannot open \"" << QDir::toNativeSeparators(fileName)
+ << "\": " << file.errorString();
+ }
return result;
}
it = m_fileBufferCache.insert(range.first.file, file.readAll());
@@ -60,10 +90,15 @@ SourceFileCache::Snippet SourceFileCache::getCodeSnippet(const CXCursor &cursor)
const unsigned pos = range.first.offset;
const unsigned end = range.second.offset;
+ Q_ASSERT(end > pos);
const QByteArray &contents = it.value();
if (end >= unsigned(contents.size())) {
- qWarning().noquote().nospace() << "Range end " << end << " is above size of "
- << range.first.file << " (" << contents.size() << ')';
+ if (errorMessage) {
+ QTextStream str(errorMessage);
+ str << "Range end " << end << " is above size of \""
+ << QDir::toNativeSeparators(getFileName(range.first.file))
+ << "\" (" << contents.size() << ')';
+ }
return result;
}
result.first = contents.constData() + pos;
@@ -102,15 +137,21 @@ bool BaseVisitor::cbHandleEndToken(const CXCursor &cursor, StartTokenResult star
BaseVisitor::CodeSnippet BaseVisitor::getCodeSnippet(const CXCursor &cursor)
{
- CodeSnippet result = m_fileCache.getCodeSnippet(cursor);
- if (result.first == nullptr)
- appendDiagnostic(Diagnostic(QStringLiteral("Unable to retrieve code snippet."), cursor, CXDiagnostic_Error));
+ QString errorMessage;
+ CodeSnippet result = m_fileCache.getCodeSnippet(cursor, &errorMessage);
+ if (result.first == nullptr && !errorMessage.isEmpty()) {
+ QString message;
+ QTextStream str(&message);
+ str << "Unable to retrieve code snippet \"" << getCursorSpelling(cursor)
+ << "\": " << errorMessage;
+ appendDiagnostic(Diagnostic(message, cursor, CXDiagnostic_Error));
+ }
return result;
}
QString BaseVisitor::getCodeSnippetString(const CXCursor &cursor)
{
- CodeSnippet result = m_fileCache.getCodeSnippet(cursor);
+ CodeSnippet result = getCodeSnippet(cursor);
return result.first != nullptr
? QString::fromUtf8(result.first, int(result.second - result.first))
: QString();
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangparser.h b/sources/shiboken2/ApiExtractor/clangparser/clangparser.h
index 4248be853..825de331c 100644
--- a/sources/shiboken2/ApiExtractor/clangparser/clangparser.h
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangparser.h
@@ -45,12 +45,15 @@ class SourceFileCache {
public:
using Snippet = QPair<const char *, const char *>;
- Snippet getCodeSnippet(const CXCursor &cursor);
+ Snippet getCodeSnippet(const CXCursor &cursor, QString *errorMessage = nullptr);
+ QString getFileName(CXFile file);
private:
- using FileBufferCache = QHash<QString, QByteArray>;
+ using FileBufferCache = QHash<CXFile, QByteArray>;
+ using FileNameCache = QHash<CXFile, QString>;
FileBufferCache m_fileBufferCache;
+ FileNameCache m_fileNameCache;
};
class BaseVisitor {
@@ -74,6 +77,8 @@ public:
StartTokenResult cbHandleStartToken(const CXCursor &cursor);
bool cbHandleEndToken(const CXCursor &cursor, StartTokenResult startResult);
+ QString getFileName(CXFile file) { return m_fileCache.getFileName(file); }
+
CodeSnippet getCodeSnippet(const CXCursor &cursor);
QString getCodeSnippetString(const CXCursor &cursor);
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp
index df2476100..6bf2e3ab0 100644
--- a/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp
@@ -60,15 +60,25 @@ QtCompatHashFunctionType qHash(const CXType &ct, QtCompatHashFunctionType seed)
namespace clang {
+bool SourceLocation::equals(const SourceLocation &rhs) const
+{
+ return file == rhs.file && offset == rhs.offset;
+}
+
SourceLocation getExpansionLocation(const CXSourceLocation &location)
{
SourceLocation result;
- CXFile file; // void *
- clang_getExpansionLocation(location, &file, &result.line, &result.column, &result.offset);
+ clang_getExpansionLocation(location, &result.file, &result.line, &result.column, &result.offset);
+ return result;
+}
+
+QString getFileName(CXFile file)
+{
+ QString result;
const CXString cxFileName = clang_getFileName(file);
// Has been observed to be 0 for invalid locations
if (const char *cFileName = clang_getCString(cxFileName))
- result.file = QString::fromUtf8(cFileName);
+ result = QString::fromUtf8(cFileName);
clang_disposeString(cxFileName);
return result;
}
@@ -226,7 +236,7 @@ QDebug operator<<(QDebug s, const SourceLocation &l)
QDebugStateSaver saver(s);
s.nospace();
s.noquote();
- s << QDir::toNativeSeparators(l.file) << ':' << l.line;
+ s << QDir::toNativeSeparators(clang::getFileName(l.file)) << ':' << l.line;
if (l.column)
s << ':' << l.column;
return s;
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangutils.h b/sources/shiboken2/ApiExtractor/clangparser/clangutils.h
index 5f005bd5d..41d0af460 100644
--- a/sources/shiboken2/ApiExtractor/clangparser/clangutils.h
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangutils.h
@@ -62,16 +62,24 @@ inline bool isCursorValid(const CXCursor &c)
return c.kind < CXCursor_FirstInvalid || c.kind > CXCursor_LastInvalid;
}
+QString getFileName(CXFile file); // Uncached,see BaseVisitor for a cached version
+
struct SourceLocation
{
- int compare(const SourceLocation &rhs) const;
+ bool equals(const SourceLocation &rhs) const;
- QString file;
+ CXFile file;
unsigned line = 0;
unsigned column = 0;
unsigned offset = 0;
};
+inline bool operator==(const SourceLocation &l1, const SourceLocation &l2)
+{ return l1.equals(l2); }
+
+inline bool operator!=(const SourceLocation &l1, const SourceLocation &l2)
+{ return !l1.equals(l2); }
+
SourceLocation getExpansionLocation(const CXSourceLocation &location);
using SourceRange =QPair<SourceLocation, SourceLocation>;
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index d0c144358..001c6d902 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -939,9 +939,10 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s,
s << INDENT << returnStatement(defaultReturnExpr.returnValue()) << Qt::endl;
}
- s << INDENT << "Shiboken::AutoDecRef " << PYTHON_OVERRIDE_VAR << "(Shiboken::BindingManager::instance().getOverride(this, \"";
- s << funcName << "\"));\n";
-
+ s << INDENT << "static PyObject *pyFuncName = Shiboken::String::createStaticString(\""
+ << funcName << "\");\n";
+ s << INDENT << "Shiboken::AutoDecRef " << PYTHON_OVERRIDE_VAR
+ << "(Shiboken::BindingManager::instance().getOverride(this, pyFuncName));\n";
s << INDENT << "if (" << PYTHON_OVERRIDE_VAR << ".isNull()) {\n";
{
Indentation indentation(INDENT);
diff --git a/sources/shiboken2/libshiboken/bindingmanager.cpp b/sources/shiboken2/libshiboken/bindingmanager.cpp
index 1ab8dd089..1c38da81c 100644
--- a/sources/shiboken2/libshiboken/bindingmanager.cpp
+++ b/sources/shiboken2/libshiboken/bindingmanager.cpp
@@ -273,7 +273,7 @@ SbkObject *BindingManager::retrieveWrapper(const void *cptr)
return iter->second;
}
-PyObject *BindingManager::getOverride(const void *cptr, const char *methodName)
+PyObject *BindingManager::getOverride(const void *cptr, PyObject *methodName)
{
SbkObject *wrapper = retrieveWrapper(cptr);
// The refcount can be 0 if the object is dieing and someone called
@@ -282,15 +282,14 @@ PyObject *BindingManager::getOverride(const void *cptr, const char *methodName)
return nullptr;
if (wrapper->ob_dict) {
- PyObject *method = PyDict_GetItemString(wrapper->ob_dict, methodName);
+ PyObject *method = PyDict_GetItem(wrapper->ob_dict, methodName);
if (method) {
Py_INCREF(reinterpret_cast<PyObject *>(method));
return method;
}
}
- Shiboken::AutoDecRef pyMethodName(Shiboken::String::fromCString(methodName));
- PyObject *method = PyObject_GetAttr(reinterpret_cast<PyObject *>(wrapper), pyMethodName);
+ PyObject *method = PyObject_GetAttr(reinterpret_cast<PyObject *>(wrapper), methodName);
if (method && PyMethod_Check(method)
&& PyMethod_GET_SELF(method) == reinterpret_cast<PyObject *>(wrapper)) {
@@ -302,7 +301,7 @@ PyObject *BindingManager::getOverride(const void *cptr, const char *methodName)
for (int i = 1; i < PyTuple_GET_SIZE(mro) - 1; i++) {
auto *parent = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, i));
if (parent->tp_dict) {
- defaultMethod = PyDict_GetItem(parent->tp_dict, pyMethodName);
+ defaultMethod = PyDict_GetItem(parent->tp_dict, methodName);
if (defaultMethod && PyMethod_GET_FUNCTION(method) != defaultMethod)
return method;
}
diff --git a/sources/shiboken2/libshiboken/bindingmanager.h b/sources/shiboken2/libshiboken/bindingmanager.h
index ba5535347..0bcde196f 100644
--- a/sources/shiboken2/libshiboken/bindingmanager.h
+++ b/sources/shiboken2/libshiboken/bindingmanager.h
@@ -73,7 +73,7 @@ public:
void addToDeletionInMainThread(const DestructorEntry &);
SbkObject *retrieveWrapper(const void *cptr);
- PyObject *getOverride(const void *cptr, const char *methodName);
+ PyObject *getOverride(const void *cptr, PyObject *methodName);
void addClassInheritance(SbkObjectType *parent, SbkObjectType *child);
/**
diff --git a/sources/shiboken2/libshiboken/sbkstring.cpp b/sources/shiboken2/libshiboken/sbkstring.cpp
index 38bb105d0..7fb7d5730 100644
--- a/sources/shiboken2/libshiboken/sbkstring.cpp
+++ b/sources/shiboken2/libshiboken/sbkstring.cpp
@@ -41,7 +41,7 @@
#include "sbkstaticstrings_p.h"
#include "autodecref.h"
-#include <vector>
+#include <set>
namespace Shiboken
{
@@ -236,7 +236,7 @@ Py_ssize_t len(PyObject *str)
// But this is a global fault in shiboken. We are missing a true
// finalization like in all other modules.
-using StaticStrings = std::vector<PyObject *>;
+using StaticStrings = std::set<PyObject *>;
static StaticStrings &staticStrings()
{
@@ -256,7 +256,7 @@ PyObject *createStaticString(const char *str)
PyErr_Print();
Py_FatalError("unexpected error in createStaticString()");
}
- staticStrings().push_back(result);
+ staticStrings().insert(result);
return result;
}