Bug 1833552 - Reformat mozsearch clang plugin using LLVM style. r=asuth
This is a bump of the Mozsearch clang plugin and was reviewed upstream: https://github.com/mozsearch/mozsearch/pull/839 Differential Revision: https://phabricator.services.mozilla.com/D230454
This commit is contained in:
@@ -31,12 +31,13 @@ using namespace clang;
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template <typename InputIt>
|
template <typename InputIt>
|
||||||
bool hasReverseQualifiedName(InputIt first, InputIt last, const NamedDecl &tag)
|
bool hasReverseQualifiedName(InputIt first, InputIt last,
|
||||||
{
|
const NamedDecl &tag) {
|
||||||
const NamedDecl *currentDecl = &tag;
|
const NamedDecl *currentDecl = &tag;
|
||||||
InputIt currentName;
|
InputIt currentName;
|
||||||
for (currentName = first; currentName != last; currentName++) {
|
for (currentName = first; currentName != last; currentName++) {
|
||||||
if (!currentDecl || !currentDecl->getIdentifier() || currentDecl->getName() != *currentName)
|
if (!currentDecl || !currentDecl->getIdentifier() ||
|
||||||
|
currentDecl->getName() != *currentName)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
currentDecl = dyn_cast<NamedDecl>(currentDecl->getDeclContext());
|
currentDecl = dyn_cast<NamedDecl>(currentDecl->getDeclContext());
|
||||||
@@ -50,20 +51,21 @@ bool hasReverseQualifiedName(InputIt first, InputIt last, const NamedDecl &tag)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMozillaJniObjectBase(const CXXRecordDecl &klass)
|
bool isMozillaJniObjectBase(const CXXRecordDecl &klass) {
|
||||||
{
|
const auto qualifiedName =
|
||||||
const auto qualifiedName = std::array<StringRef, 3>{"mozilla", "jni", "ObjectBase"};
|
std::array<StringRef, 3>{"mozilla", "jni", "ObjectBase"};
|
||||||
return hasReverseQualifiedName(qualifiedName.crbegin(), qualifiedName.crend(), klass);
|
return hasReverseQualifiedName(qualifiedName.crbegin(), qualifiedName.crend(),
|
||||||
|
klass);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMozillaJniNativeImpl(const CXXRecordDecl &klass)
|
bool isMozillaJniNativeImpl(const CXXRecordDecl &klass) {
|
||||||
{
|
const auto qualifiedName =
|
||||||
const auto qualifiedName = std::array<StringRef, 3>{"mozilla", "jni", "NativeImpl"};
|
std::array<StringRef, 3>{"mozilla", "jni", "NativeImpl"};
|
||||||
return hasReverseQualifiedName(qualifiedName.crbegin(), qualifiedName.crend(), klass);
|
return hasReverseQualifiedName(qualifiedName.crbegin(), qualifiedName.crend(),
|
||||||
|
klass);
|
||||||
}
|
}
|
||||||
|
|
||||||
const NamedDecl *fieldNamed(StringRef name, const RecordDecl &strukt)
|
const NamedDecl *fieldNamed(StringRef name, const RecordDecl &strukt) {
|
||||||
{
|
|
||||||
for (const auto *decl : strukt.decls()) {
|
for (const auto *decl : strukt.decls()) {
|
||||||
const auto *namedDecl = dyn_cast<VarDecl>(decl);
|
const auto *namedDecl = dyn_cast<VarDecl>(decl);
|
||||||
if (!namedDecl)
|
if (!namedDecl)
|
||||||
@@ -78,8 +80,7 @@ const NamedDecl *fieldNamed(StringRef name, const RecordDecl &strukt)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<StringRef> nameFieldValue(const RecordDecl &strukt)
|
optional<StringRef> nameFieldValue(const RecordDecl &strukt) {
|
||||||
{
|
|
||||||
const auto *nameField = dyn_cast_or_null<VarDecl>(fieldNamed("name", strukt));
|
const auto *nameField = dyn_cast_or_null<VarDecl>(fieldNamed("name", strukt));
|
||||||
if (!nameField)
|
if (!nameField)
|
||||||
return {};
|
return {};
|
||||||
@@ -107,18 +108,14 @@ struct AbstractBinding {
|
|||||||
"jvm",
|
"jvm",
|
||||||
};
|
};
|
||||||
|
|
||||||
static optional<Lang> langFromString(StringRef langName)
|
static optional<Lang> langFromString(StringRef langName) {
|
||||||
{
|
|
||||||
const auto it = std::find(langNames.begin(), langNames.end(), langName);
|
const auto it = std::find(langNames.begin(), langNames.end(), langName);
|
||||||
if (it == langNames.end())
|
if (it == langNames.end())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return Lang(it - langNames.begin());
|
return Lang(it - langNames.begin());
|
||||||
}
|
}
|
||||||
static StringRef stringFromLang(Lang lang)
|
static StringRef stringFromLang(Lang lang) { return langNames[size_t(lang)]; }
|
||||||
{
|
|
||||||
return langNames[size_t(lang)];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subset of tools/analysis/BindingSlotKind
|
// Subset of tools/analysis/BindingSlotKind
|
||||||
enum class Kind {
|
enum class Kind {
|
||||||
@@ -130,34 +127,28 @@ struct AbstractBinding {
|
|||||||
};
|
};
|
||||||
static constexpr size_t KindLength = 5;
|
static constexpr size_t KindLength = 5;
|
||||||
static constexpr std::array<StringRef, KindLength> kindNames = {
|
static constexpr std::array<StringRef, KindLength> kindNames = {
|
||||||
"class",
|
"class", "method", "getter", "setter", "const",
|
||||||
"method",
|
|
||||||
"getter",
|
|
||||||
"setter",
|
|
||||||
"const",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static optional<Kind> kindFromString(StringRef kindName)
|
static optional<Kind> kindFromString(StringRef kindName) {
|
||||||
{
|
|
||||||
const auto it = std::find(kindNames.begin(), kindNames.end(), kindName);
|
const auto it = std::find(kindNames.begin(), kindNames.end(), kindName);
|
||||||
if (it == kindNames.end())
|
if (it == kindNames.end())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return Kind(it - kindNames.begin());
|
return Kind(it - kindNames.begin());
|
||||||
}
|
}
|
||||||
static StringRef stringFromKind(Kind kind)
|
static StringRef stringFromKind(Kind kind) { return kindNames[size_t(kind)]; }
|
||||||
{
|
|
||||||
return kindNames[size_t(kind)];
|
|
||||||
}
|
|
||||||
|
|
||||||
Lang lang;
|
Lang lang;
|
||||||
Kind kind;
|
Kind kind;
|
||||||
StringRef symbol;
|
StringRef symbol;
|
||||||
};
|
};
|
||||||
constexpr size_t AbstractBinding::KindLength;
|
constexpr size_t AbstractBinding::KindLength;
|
||||||
constexpr std::array<StringRef, AbstractBinding::KindLength> AbstractBinding::kindNames;
|
constexpr std::array<StringRef, AbstractBinding::KindLength>
|
||||||
|
AbstractBinding::kindNames;
|
||||||
constexpr size_t AbstractBinding::LangLength;
|
constexpr size_t AbstractBinding::LangLength;
|
||||||
constexpr std::array<StringRef, AbstractBinding::LangLength> AbstractBinding::langNames;
|
constexpr std::array<StringRef, AbstractBinding::LangLength>
|
||||||
|
AbstractBinding::langNames;
|
||||||
|
|
||||||
struct BindingTo : public AbstractBinding {
|
struct BindingTo : public AbstractBinding {
|
||||||
BindingTo(AbstractBinding b) : AbstractBinding(std::move(b)) {}
|
BindingTo(AbstractBinding b) : AbstractBinding(std::move(b)) {}
|
||||||
@@ -172,24 +163,25 @@ struct BoundAs : public AbstractBinding {
|
|||||||
constexpr StringRef BoundAs::ANNOTATION;
|
constexpr StringRef BoundAs::ANNOTATION;
|
||||||
|
|
||||||
template <typename B>
|
template <typename B>
|
||||||
void setBindingAttr(ASTContext &C, Decl &decl, B binding)
|
void setBindingAttr(ASTContext &C, Decl &decl, B binding) {
|
||||||
{
|
|
||||||
#if CLANG_VERSION_MAJOR >= 18
|
#if CLANG_VERSION_MAJOR >= 18
|
||||||
auto utf8 = StringLiteralKind::UTF8;
|
auto utf8 = StringLiteralKind::UTF8;
|
||||||
#else
|
#else
|
||||||
auto utf8 = StringLiteral::UTF8;
|
auto utf8 = StringLiteral::UTF8;
|
||||||
#endif
|
#endif
|
||||||
// recent LLVM: CreateImplicit then setDelayedArgs
|
// recent LLVM: CreateImplicit then setDelayedArgs
|
||||||
Expr *langExpr = StringLiteral::Create(C, AbstractBinding::stringFromLang(binding.lang), utf8, false, {}, {});
|
Expr *langExpr = StringLiteral::Create(
|
||||||
Expr *kindExpr = StringLiteral::Create(C, AbstractBinding::stringFromKind(binding.kind), utf8, false, {}, {});
|
C, AbstractBinding::stringFromLang(binding.lang), utf8, false, {}, {});
|
||||||
Expr *symbolExpr = StringLiteral::Create(C, binding.symbol, utf8, false, {}, {});
|
Expr *kindExpr = StringLiteral::Create(
|
||||||
|
C, AbstractBinding::stringFromKind(binding.kind), utf8, false, {}, {});
|
||||||
|
Expr *symbolExpr =
|
||||||
|
StringLiteral::Create(C, binding.symbol, utf8, false, {}, {});
|
||||||
auto **args = new (C, 16) Expr *[3]{langExpr, kindExpr, symbolExpr};
|
auto **args = new (C, 16) Expr *[3]{langExpr, kindExpr, symbolExpr};
|
||||||
auto *attr = AnnotateAttr::CreateImplicit(C, B::ANNOTATION, args, 3);
|
auto *attr = AnnotateAttr::CreateImplicit(C, B::ANNOTATION, args, 3);
|
||||||
decl.addAttr(attr);
|
decl.addAttr(attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<AbstractBinding> readBinding(const AnnotateAttr &attr)
|
optional<AbstractBinding> readBinding(const AnnotateAttr &attr) {
|
||||||
{
|
|
||||||
if (attr.args_size() != 3)
|
if (attr.args_size() != 3)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
@@ -199,9 +191,12 @@ optional<AbstractBinding> readBinding(const AnnotateAttr &attr)
|
|||||||
if (!langExpr || !kindExpr || !symbolExpr)
|
if (!langExpr || !kindExpr || !symbolExpr)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const auto *langName = dyn_cast<StringLiteral>(langExpr->IgnoreUnlessSpelledInSource());
|
const auto *langName =
|
||||||
const auto *kindName = dyn_cast<StringLiteral>(kindExpr->IgnoreUnlessSpelledInSource());
|
dyn_cast<StringLiteral>(langExpr->IgnoreUnlessSpelledInSource());
|
||||||
const auto *symbol = dyn_cast<StringLiteral>(symbolExpr->IgnoreUnlessSpelledInSource());
|
const auto *kindName =
|
||||||
|
dyn_cast<StringLiteral>(kindExpr->IgnoreUnlessSpelledInSource());
|
||||||
|
const auto *symbol =
|
||||||
|
dyn_cast<StringLiteral>(symbolExpr->IgnoreUnlessSpelledInSource());
|
||||||
if (!langName || !kindName || !symbol)
|
if (!langName || !kindName || !symbol)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
@@ -218,8 +213,7 @@ optional<AbstractBinding> readBinding(const AnnotateAttr &attr)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<BindingTo> getBindingTo(const Decl &decl)
|
optional<BindingTo> getBindingTo(const Decl &decl) {
|
||||||
{
|
|
||||||
for (const auto *attr : decl.specific_attrs<AnnotateAttr>()) {
|
for (const auto *attr : decl.specific_attrs<AnnotateAttr>()) {
|
||||||
if (attr->getAnnotation() != BindingTo::ANNOTATION)
|
if (attr->getAnnotation() != BindingTo::ANNOTATION)
|
||||||
continue;
|
continue;
|
||||||
@@ -234,8 +228,7 @@ optional<BindingTo> getBindingTo(const Decl &decl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// C++23: turn into generator
|
// C++23: turn into generator
|
||||||
std::vector<BoundAs> getBoundAs(const Decl &decl)
|
std::vector<BoundAs> getBoundAs(const Decl &decl) {
|
||||||
{
|
|
||||||
std::vector<BoundAs> found;
|
std::vector<BoundAs> found;
|
||||||
|
|
||||||
for (const auto *attr : decl.specific_attrs<AnnotateAttr>()) {
|
for (const auto *attr : decl.specific_attrs<AnnotateAttr>()) {
|
||||||
@@ -252,8 +245,7 @@ std::vector<BoundAs> getBoundAs(const Decl &decl)
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
class FindCallCall : private RecursiveASTVisitor<FindCallCall>
|
class FindCallCall : private RecursiveASTVisitor<FindCallCall> {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
struct Result {
|
struct Result {
|
||||||
using Kind = AbstractBinding::Kind;
|
using Kind = AbstractBinding::Kind;
|
||||||
@@ -262,8 +254,7 @@ public:
|
|||||||
StringRef name;
|
StringRef name;
|
||||||
};
|
};
|
||||||
|
|
||||||
static optional<Result> search(Stmt *statement)
|
static optional<Result> search(Stmt *statement) {
|
||||||
{
|
|
||||||
FindCallCall finder;
|
FindCallCall finder;
|
||||||
finder.TraverseStmt(statement);
|
finder.TraverseStmt(statement);
|
||||||
return finder.result;
|
return finder.result;
|
||||||
@@ -275,7 +266,8 @@ private:
|
|||||||
friend RecursiveASTVisitor<FindCallCall>;
|
friend RecursiveASTVisitor<FindCallCall>;
|
||||||
|
|
||||||
optional<Result> tryParseCallCall(CallExpr *callExpr) {
|
optional<Result> tryParseCallCall(CallExpr *callExpr) {
|
||||||
const auto *callee = dyn_cast_or_null<CXXMethodDecl>(callExpr->getDirectCallee());
|
const auto *callee =
|
||||||
|
dyn_cast_or_null<CXXMethodDecl>(callExpr->getDirectCallee());
|
||||||
if (!callee)
|
if (!callee)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
@@ -287,7 +279,8 @@ private:
|
|||||||
if (action != "Call" && action != "Get" && action != "Set")
|
if (action != "Call" && action != "Get" && action != "Set")
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const auto *parentClass = dyn_cast_or_null<ClassTemplateSpecializationDecl>(callee->getParent());
|
const auto *parentClass =
|
||||||
|
dyn_cast_or_null<ClassTemplateSpecializationDecl>(callee->getParent());
|
||||||
|
|
||||||
if (!parentClass)
|
if (!parentClass)
|
||||||
return {};
|
return {};
|
||||||
@@ -318,7 +311,8 @@ private:
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto *templateArg = parentClass->getTemplateArgs().get(0).getAsType()->getAsRecordDecl();
|
const auto *templateArg =
|
||||||
|
parentClass->getTemplateArgs().get(0).getAsType()->getAsRecordDecl();
|
||||||
|
|
||||||
if (!templateArg)
|
if (!templateArg)
|
||||||
return {};
|
return {};
|
||||||
@@ -334,16 +328,15 @@ private:
|
|||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
bool VisitCallExpr(CallExpr *callExpr)
|
bool VisitCallExpr(CallExpr *callExpr) {
|
||||||
{
|
|
||||||
return !(result = tryParseCallCall(callExpr));
|
return !(result = tryParseCallCall(callExpr));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr StringRef JVM_SCIP_SYMBOL_PREFIX = "S_jvm_";
|
constexpr StringRef JVM_SCIP_SYMBOL_PREFIX = "S_jvm_";
|
||||||
|
|
||||||
std::string javaScipSymbol(StringRef prefix, StringRef name, AbstractBinding::Kind kind)
|
std::string javaScipSymbol(StringRef prefix, StringRef name,
|
||||||
{
|
AbstractBinding::Kind kind) {
|
||||||
auto symbol = (prefix + name).str();
|
auto symbol = (prefix + name).str();
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
@@ -364,8 +357,7 @@ std::string javaScipSymbol(StringRef prefix, StringRef name, AbstractBinding::Ki
|
|||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addSlotOwnerAttribute(llvm::json::OStream &J, const Decl &decl)
|
void addSlotOwnerAttribute(llvm::json::OStream &J, const Decl &decl) {
|
||||||
{
|
|
||||||
if (const auto bindingTo = getBindingTo(decl)) {
|
if (const auto bindingTo = getBindingTo(decl)) {
|
||||||
J.attributeBegin("slotOwner");
|
J.attributeBegin("slotOwner");
|
||||||
J.objectBegin();
|
J.objectBegin();
|
||||||
@@ -377,8 +369,7 @@ void addSlotOwnerAttribute(llvm::json::OStream &J, const Decl &decl)
|
|||||||
J.attributeEnd();
|
J.attributeEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void addBindingSlotsAttribute(llvm::json::OStream &J, const Decl &decl)
|
void addBindingSlotsAttribute(llvm::json::OStream &J, const Decl &decl) {
|
||||||
{
|
|
||||||
const auto allBoundAs = getBoundAs(decl);
|
const auto allBoundAs = getBoundAs(decl);
|
||||||
if (!allBoundAs.empty()) {
|
if (!allBoundAs.empty()) {
|
||||||
J.attributeBegin("bindingSlots");
|
J.attributeBegin("bindingSlots");
|
||||||
@@ -396,7 +387,8 @@ void addBindingSlotsAttribute(llvm::json::OStream &J, const Decl &decl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The mangling scheme is documented at https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html
|
// The mangling scheme is documented at
|
||||||
|
// https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html
|
||||||
// The main takeaways are:
|
// The main takeaways are:
|
||||||
// - _0xxxx is the utf16 code unit xxxx
|
// - _0xxxx is the utf16 code unit xxxx
|
||||||
// - _1 is _
|
// - _1 is _
|
||||||
@@ -405,12 +397,13 @@ void addBindingSlotsAttribute(llvm::json::OStream &J, const Decl &decl)
|
|||||||
// - __ is the separator between function name and overload specification
|
// - __ is the separator between function name and overload specification
|
||||||
// - _ is otherwise the separator between packages/classes/methods
|
// - _ is otherwise the separator between packages/classes/methods
|
||||||
//
|
//
|
||||||
// This method takes a StringRef & and mutates it and can be called twice on a Jnicall function name to get
|
// This method takes a StringRef & and mutates it and can be called twice on a
|
||||||
|
// Jnicall function name to get
|
||||||
// first the demangled name
|
// first the demangled name
|
||||||
// second the demangled overload specification
|
// second the demangled overload specification
|
||||||
// But we don't use the later for now because we have no way to map that to how SCIP resolves overloads.
|
// But we don't use the later for now because we have no way to map that to how
|
||||||
optional<std::string> demangleJnicallPart(StringRef &remainder)
|
// SCIP resolves overloads.
|
||||||
{
|
optional<std::string> demangleJnicallPart(StringRef &remainder) {
|
||||||
std::string demangled;
|
std::string demangled;
|
||||||
|
|
||||||
std::mbstate_t ps = {};
|
std::mbstate_t ps = {};
|
||||||
@@ -467,7 +460,8 @@ optional<std::string> demangleJnicallPart(StringRef &remainder)
|
|||||||
default:
|
default:
|
||||||
// either:
|
// either:
|
||||||
// * the string began with _[^0-3], which is not supposed to happen; or
|
// * the string began with _[^0-3], which is not supposed to happen; or
|
||||||
// * we reached __[^0-3] meaning we finished the first part of the name and remainder holds the overload specification
|
// * we reached __[^0-3] meaning we finished the first part of the name
|
||||||
|
// and remainder holds the overload specification
|
||||||
return demangled;
|
return demangled;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -483,8 +477,8 @@ optional<std::string> demangleJnicallPart(StringRef &remainder)
|
|||||||
return demangled;
|
return demangled;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<std::string> scipSymbolFromJnicallFunctionName(StringRef functionName)
|
optional<std::string>
|
||||||
{
|
scipSymbolFromJnicallFunctionName(StringRef functionName) {
|
||||||
if (!functionName.consume_front("Java_"))
|
if (!functionName.consume_front("Java_"))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
@@ -493,7 +487,8 @@ optional<std::string> scipSymbolFromJnicallFunctionName(StringRef functionName)
|
|||||||
if (!demangledName || demangledName->empty())
|
if (!demangledName || demangledName->empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
// demangleJavaName returns something like .some.package.Class$InnerClass.method
|
// demangleJavaName returns something like
|
||||||
|
// .some.package.Class$InnerClass.method
|
||||||
// - prepend S_jvm_
|
// - prepend S_jvm_
|
||||||
// - remove the leading dot
|
// - remove the leading dot
|
||||||
// - replace the last dot with a #
|
// - replace the last dot with a #
|
||||||
@@ -508,8 +503,10 @@ optional<std::string> scipSymbolFromJnicallFunctionName(StringRef functionName)
|
|||||||
std::replace(symbol.begin(), symbol.end(), '.', '/');
|
std::replace(symbol.begin(), symbol.end(), '.', '/');
|
||||||
std::replace(symbol.begin(), symbol.end(), '$', '#');
|
std::replace(symbol.begin(), symbol.end(), '$', '#');
|
||||||
|
|
||||||
// Keep track of how many times we have seen this method, to build the ([+overloadNumber]). suffix.
|
// Keep track of how many times we have seen this method, to build the
|
||||||
// This assumes this function is called on C function definitions in the same order the matching overloads are declared in Java.
|
// ([+overloadNumber]). suffix. This assumes this function is called on C
|
||||||
|
// function definitions in the same order the matching overloads are declared
|
||||||
|
// in Java.
|
||||||
static std::unordered_map<std::string, uint> jnicallFunctions;
|
static std::unordered_map<std::string, uint> jnicallFunctions;
|
||||||
auto &overloadNumber = jnicallFunctions[symbol];
|
auto &overloadNumber = jnicallFunctions[symbol];
|
||||||
|
|
||||||
@@ -530,8 +527,7 @@ optional<std::string> scipSymbolFromJnicallFunctionName(StringRef functionName)
|
|||||||
// {
|
// {
|
||||||
// static constexpr char name[] = "[nameFieldValue]";
|
// static constexpr char name[] = "[nameFieldValue]";
|
||||||
// }
|
// }
|
||||||
void findBindingToJavaClass(ASTContext &C, CXXRecordDecl &klass)
|
void findBindingToJavaClass(ASTContext &C, CXXRecordDecl &klass) {
|
||||||
{
|
|
||||||
for (const auto &baseSpecifier : klass.bases()) {
|
for (const auto &baseSpecifier : klass.bases()) {
|
||||||
const auto *base = baseSpecifier.getType()->getAsCXXRecordDecl();
|
const auto *base = baseSpecifier.getType()->getAsCXXRecordDecl();
|
||||||
if (!base)
|
if (!base)
|
||||||
@@ -544,7 +540,8 @@ void findBindingToJavaClass(ASTContext &C, CXXRecordDecl &klass)
|
|||||||
if (!name)
|
if (!name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto symbol = javaScipSymbol(JVM_SCIP_SYMBOL_PREFIX, *name, BindingTo::Kind::Class);
|
const auto symbol =
|
||||||
|
javaScipSymbol(JVM_SCIP_SYMBOL_PREFIX, *name, BindingTo::Kind::Class);
|
||||||
const auto binding = BindingTo{{
|
const auto binding = BindingTo{{
|
||||||
.lang = BindingTo::Lang::Jvm,
|
.lang = BindingTo::Lang::Jvm,
|
||||||
.kind = BindingTo::Kind::Class,
|
.kind = BindingTo::Kind::Class,
|
||||||
@@ -556,10 +553,10 @@ void findBindingToJavaClass(ASTContext &C, CXXRecordDecl &klass)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// When a Java method is marked as native, the JRE looks by default for a function
|
// When a Java method is marked as native, the JRE looks by default for a
|
||||||
// named Java_<mangled method name>[__<mangled overload specification>].
|
// function named Java_<mangled method name>[__<mangled overload
|
||||||
void findBindingToJavaFunction(ASTContext &C, FunctionDecl &function)
|
// specification>].
|
||||||
{
|
void findBindingToJavaFunction(ASTContext &C, FunctionDecl &function) {
|
||||||
const auto *identifier = function.getIdentifier();
|
const auto *identifier = function.getIdentifier();
|
||||||
if (!identifier)
|
if (!identifier)
|
||||||
return;
|
return;
|
||||||
@@ -590,8 +587,7 @@ void findBindingToJavaFunction(ASTContext &C, FunctionDecl &function)
|
|||||||
// ...
|
// ...
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
void findBindingToJavaMember(ASTContext &C, CXXMethodDecl &method)
|
void findBindingToJavaMember(ASTContext &C, CXXMethodDecl &method) {
|
||||||
{
|
|
||||||
const auto *parent = method.getParent();
|
const auto *parent = method.getParent();
|
||||||
if (!parent)
|
if (!parent)
|
||||||
return;
|
return;
|
||||||
@@ -607,7 +603,8 @@ void findBindingToJavaMember(ASTContext &C, CXXMethodDecl &method)
|
|||||||
if (!found)
|
if (!found)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto symbol = javaScipSymbol(classBinding->symbol, found->name, found->kind);
|
const auto symbol =
|
||||||
|
javaScipSymbol(classBinding->symbol, found->name, found->kind);
|
||||||
const auto binding = BindingTo{{
|
const auto binding = BindingTo{{
|
||||||
.lang = BindingTo::Lang::Jvm,
|
.lang = BindingTo::Lang::Jvm,
|
||||||
.kind = found->kind,
|
.kind = found->kind,
|
||||||
@@ -629,8 +626,7 @@ void findBindingToJavaMember(ASTContext &C, CXXMethodDecl &method)
|
|||||||
// ...
|
// ...
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
void findBindingToJavaConstant(ASTContext &C, VarDecl &field)
|
void findBindingToJavaConstant(ASTContext &C, VarDecl &field) {
|
||||||
{
|
|
||||||
const auto *parent = dyn_cast_or_null<CXXRecordDecl>(field.getDeclContext());
|
const auto *parent = dyn_cast_or_null<CXXRecordDecl>(field.getDeclContext());
|
||||||
if (!parent)
|
if (!parent)
|
||||||
return;
|
return;
|
||||||
@@ -639,7 +635,8 @@ void findBindingToJavaConstant(ASTContext &C, VarDecl &field)
|
|||||||
if (!classBinding)
|
if (!classBinding)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto symbol = javaScipSymbol(classBinding->symbol, field.getName(), BindingTo::Kind::Const);
|
const auto symbol = javaScipSymbol(classBinding->symbol, field.getName(),
|
||||||
|
BindingTo::Kind::Const);
|
||||||
const auto binding = BindingTo{{
|
const auto binding = BindingTo{{
|
||||||
.lang = BindingTo::Lang::Jvm,
|
.lang = BindingTo::Lang::Jvm,
|
||||||
.kind = BindingTo::Kind::Const,
|
.kind = BindingTo::Kind::Const,
|
||||||
@@ -667,22 +664,23 @@ void findBindingToJavaConstant(ASTContext &C, VarDecl &field)
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
|
void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass) {
|
||||||
{
|
|
||||||
for (const auto &baseSpecifier : klass.bases()) {
|
for (const auto &baseSpecifier : klass.bases()) {
|
||||||
const auto *base = baseSpecifier.getType()->getAsCXXRecordDecl();
|
const auto *base = baseSpecifier.getType()->getAsCXXRecordDecl();
|
||||||
if (!base)
|
if (!base)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (const auto &baseBaseSpecifier : base->bases()) {
|
for (const auto &baseBaseSpecifier : base->bases()) {
|
||||||
const auto *baseBase = dyn_cast_or_null<ClassTemplateSpecializationDecl>(baseBaseSpecifier.getType()->getAsCXXRecordDecl());
|
const auto *baseBase = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
|
||||||
|
baseBaseSpecifier.getType()->getAsCXXRecordDecl());
|
||||||
if (!baseBase)
|
if (!baseBase)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!isMozillaJniNativeImpl(*baseBase))
|
if (!isMozillaJniNativeImpl(*baseBase))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto *wrapper = baseBase->getTemplateArgs().get(0).getAsType()->getAsCXXRecordDecl();
|
const auto *wrapper =
|
||||||
|
baseBase->getTemplateArgs().get(0).getAsType()->getAsCXXRecordDecl();
|
||||||
|
|
||||||
if (!wrapper)
|
if (!wrapper)
|
||||||
continue;
|
continue;
|
||||||
@@ -691,7 +689,8 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
|
|||||||
if (!name)
|
if (!name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto javaClassSymbol = javaScipSymbol(JVM_SCIP_SYMBOL_PREFIX, *name, BoundAs::Kind::Class);
|
const auto javaClassSymbol =
|
||||||
|
javaScipSymbol(JVM_SCIP_SYMBOL_PREFIX, *name, BoundAs::Kind::Class);
|
||||||
const auto classBinding = BoundAs{{
|
const auto classBinding = BoundAs{{
|
||||||
.lang = BoundAs::Lang::Jvm,
|
.lang = BoundAs::Lang::Jvm,
|
||||||
.kind = BoundAs::Kind::Class,
|
.kind = BoundAs::Kind::Class,
|
||||||
@@ -699,7 +698,8 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
|
|||||||
}};
|
}};
|
||||||
setBindingAttr(C, klass, classBinding);
|
setBindingAttr(C, klass, classBinding);
|
||||||
|
|
||||||
const auto *methodsDecl = dyn_cast_or_null<VarDecl>(fieldNamed("methods", *base));
|
const auto *methodsDecl =
|
||||||
|
dyn_cast_or_null<VarDecl>(fieldNamed("methods", *base));
|
||||||
if (!methodsDecl)
|
if (!methodsDecl)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -714,7 +714,8 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
|
|||||||
std::set<const CXXMethodDecl *> alreadyBound;
|
std::set<const CXXMethodDecl *> alreadyBound;
|
||||||
|
|
||||||
for (const auto *init : inits->inits()) {
|
for (const auto *init : inits->inits()) {
|
||||||
const auto *call = dyn_cast<CallExpr>(init->IgnoreUnlessSpelledInSource());
|
const auto *call =
|
||||||
|
dyn_cast<CallExpr>(init->IgnoreUnlessSpelledInSource());
|
||||||
if (!call)
|
if (!call)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -726,15 +727,18 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
|
|||||||
if (!templateArgs)
|
if (!templateArgs)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto *strukt = dyn_cast_or_null<RecordDecl>(templateArgs->get(0).getAsType()->getAsRecordDecl());
|
const auto *strukt = dyn_cast_or_null<RecordDecl>(
|
||||||
|
templateArgs->get(0).getAsType()->getAsRecordDecl());
|
||||||
if (!strukt)
|
if (!strukt)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto *wrapperRef = dyn_cast_or_null<DeclRefExpr>(call->getArg(0)->IgnoreUnlessSpelledInSource());
|
const auto *wrapperRef = dyn_cast_or_null<DeclRefExpr>(
|
||||||
|
call->getArg(0)->IgnoreUnlessSpelledInSource());
|
||||||
if (!wrapperRef)
|
if (!wrapperRef)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto *boundRef = dyn_cast_or_null<UnaryOperator>(wrapperRef->template_arguments().front().getArgument().getAsExpr());
|
const auto *boundRef = dyn_cast_or_null<UnaryOperator>(
|
||||||
|
wrapperRef->template_arguments().front().getArgument().getAsExpr());
|
||||||
if (!boundRef)
|
if (!boundRef)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -760,17 +764,22 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
|
|||||||
setBindingAttr(C, boundDecl, binding);
|
setBindingAttr(C, boundDecl, binding);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (auto *bound = dyn_cast_or_null<DeclRefExpr>(boundRef->getSubExpr())) {
|
if (auto *bound =
|
||||||
|
dyn_cast_or_null<DeclRefExpr>(boundRef->getSubExpr())) {
|
||||||
auto *method = dyn_cast_or_null<CXXMethodDecl>(bound->getDecl());
|
auto *method = dyn_cast_or_null<CXXMethodDecl>(bound->getDecl());
|
||||||
if (!method)
|
if (!method)
|
||||||
continue;
|
continue;
|
||||||
addToBound(*method, 0);
|
addToBound(*method, 0);
|
||||||
} else if (const auto *bound = dyn_cast_or_null<UnresolvedLookupExpr>(boundRef->getSubExpr())) {
|
} else if (const auto *bound = dyn_cast_or_null<UnresolvedLookupExpr>(
|
||||||
|
boundRef->getSubExpr())) {
|
||||||
// XXX This is hackish
|
// XXX This is hackish
|
||||||
// In case of overloads it's not obvious which one we should use
|
// In case of overloads it's not obvious which one we should use
|
||||||
// this expects the declaration order between C++ and Java to match
|
// this expects the declaration order between C++ and Java to match
|
||||||
auto declarations = std::vector<Decl*>(bound->decls_begin(), bound->decls_end());
|
auto declarations =
|
||||||
auto byLocation = [](Decl *a, Decl *b){ return a->getLocation() < b->getLocation(); };
|
std::vector<Decl *>(bound->decls_begin(), bound->decls_end());
|
||||||
|
auto byLocation = [](Decl *a, Decl *b) {
|
||||||
|
return a->getLocation() < b->getLocation();
|
||||||
|
};
|
||||||
std::sort(declarations.begin(), declarations.end(), byLocation);
|
std::sort(declarations.begin(), declarations.end(), byLocation);
|
||||||
|
|
||||||
uint i = 0;
|
uint i = 0;
|
||||||
@@ -791,8 +800,7 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void emitBindingAttributes(llvm::json::OStream &J, const Decl &decl)
|
void emitBindingAttributes(llvm::json::OStream &J, const Decl &decl) {
|
||||||
{
|
|
||||||
addSlotOwnerAttribute(J, decl);
|
addSlotOwnerAttribute(J, decl);
|
||||||
addBindingSlotsAttribute(J, decl);
|
addBindingSlotsAttribute(J, decl);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,10 @@
|
|||||||
|
|
||||||
void findBindingToJavaClass(clang::ASTContext &C, clang::CXXRecordDecl &klass);
|
void findBindingToJavaClass(clang::ASTContext &C, clang::CXXRecordDecl &klass);
|
||||||
void findBoundAsJavaClasses(clang::ASTContext &C, clang::CXXRecordDecl &klass);
|
void findBoundAsJavaClasses(clang::ASTContext &C, clang::CXXRecordDecl &klass);
|
||||||
void findBindingToJavaFunction(clang::ASTContext &C, clang::FunctionDecl &function);
|
void findBindingToJavaFunction(clang::ASTContext &C,
|
||||||
void findBindingToJavaMember(clang::ASTContext &C, clang::CXXMethodDecl &method);
|
clang::FunctionDecl &function);
|
||||||
|
void findBindingToJavaMember(clang::ASTContext &C,
|
||||||
|
clang::CXXMethodDecl &method);
|
||||||
void findBindingToJavaConstant(clang::ASTContext &C, clang::VarDecl &field);
|
void findBindingToJavaConstant(clang::ASTContext &C, clang::VarDecl &field);
|
||||||
|
|
||||||
void emitBindingAttributes(llvm::json::OStream &json, const clang::Decl &decl);
|
void emitBindingAttributes(llvm::json::OStream &json, const clang::Decl &decl);
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
#include "StringOperations.h"
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "StringOperations.h"
|
|
||||||
#else
|
#else
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@@ -50,7 +50,8 @@ void ensurePath(std::string Path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
AutoLockFile::AutoLockFile(const std::string &SrcFile, const std::string &DstFile) {
|
AutoLockFile::AutoLockFile(const std::string &SrcFile,
|
||||||
|
const std::string &DstFile) {
|
||||||
this->Filename = DstFile;
|
this->Filename = DstFile;
|
||||||
std::string Hash = hash(SrcFile);
|
std::string Hash = hash(SrcFile);
|
||||||
std::string MutexName = std::string("Local\\searchfox-") + Hash;
|
std::string MutexName = std::string("Local\\searchfox-") + Hash;
|
||||||
@@ -71,12 +72,11 @@ AutoLockFile::~AutoLockFile() {
|
|||||||
CloseHandle(Handle);
|
CloseHandle(Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AutoLockFile::success() {
|
bool AutoLockFile::success() { return Handle != NULL; }
|
||||||
return Handle != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *AutoLockFile::openTmp() {
|
FILE *AutoLockFile::openTmp() {
|
||||||
int TmpDescriptor = _open((Filename + ".tmp").c_str(), _O_WRONLY | _O_APPEND | _O_CREAT | _O_BINARY, 0666);
|
int TmpDescriptor = _open((Filename + ".tmp").c_str(),
|
||||||
|
_O_WRONLY | _O_APPEND | _O_CREAT | _O_BINARY, 0666);
|
||||||
return _fdopen(TmpDescriptor, "ab");
|
return _fdopen(TmpDescriptor, "ab");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +97,8 @@ std::string getAbsolutePath(const std::string &Filename) {
|
|||||||
return std::string(Full);
|
return std::string(Full);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
AutoLockFile::AutoLockFile(const std::string &SrcFile, const std::string &DstFile) {
|
AutoLockFile::AutoLockFile(const std::string &SrcFile,
|
||||||
|
const std::string &DstFile) {
|
||||||
this->Filename = DstFile;
|
this->Filename = DstFile;
|
||||||
FileDescriptor = open(SrcFile.c_str(), O_RDONLY);
|
FileDescriptor = open(SrcFile.c_str(), O_RDONLY);
|
||||||
if (FileDescriptor == -1) {
|
if (FileDescriptor == -1) {
|
||||||
@@ -117,7 +118,8 @@ AutoLockFile::~AutoLockFile() { close(FileDescriptor); }
|
|||||||
bool AutoLockFile::success() { return FileDescriptor != -1; }
|
bool AutoLockFile::success() { return FileDescriptor != -1; }
|
||||||
|
|
||||||
FILE *AutoLockFile::openTmp() {
|
FILE *AutoLockFile::openTmp() {
|
||||||
int TmpDescriptor = open((Filename + ".tmp").c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);
|
int TmpDescriptor =
|
||||||
|
open((Filename + ".tmp").c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);
|
||||||
return fdopen(TmpDescriptor, "ab");
|
return fdopen(TmpDescriptor, "ab");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,8 @@ FileType relativizePath(std::string& path) {
|
|||||||
// Empty filenames can get turned into Srcdir when they are resolved as
|
// Empty filenames can get turned into Srcdir when they are resolved as
|
||||||
// absolute paths, so we should exclude files that are exactly equal to
|
// absolute paths, so we should exclude files that are exactly equal to
|
||||||
// Srcdir or anything outside Srcdir.
|
// Srcdir or anything outside Srcdir.
|
||||||
if (path.length() > Srcdir.length() && path.compare(0, Srcdir.length(), Srcdir) == 0) {
|
if (path.length() > Srcdir.length() &&
|
||||||
|
path.compare(0, Srcdir.length(), Srcdir) == 0) {
|
||||||
// Remove the trailing `/' as well.
|
// Remove the trailing `/' as well.
|
||||||
path.erase(0, Srcdir.length() + 1);
|
path.erase(0, Srcdir.length() + 1);
|
||||||
return FileType::Source;
|
return FileType::Source;
|
||||||
@@ -142,13 +143,9 @@ static bool isASCII(const std::string& Input) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct RAIITracer {
|
struct RAIITracer {
|
||||||
RAIITracer(const char *log) : mLog(log) {
|
RAIITracer(const char *log) : mLog(log) { printf("<%s>\n", mLog); }
|
||||||
printf("<%s>\n", mLog);
|
|
||||||
}
|
|
||||||
|
|
||||||
~RAIITracer() {
|
~RAIITracer() { printf("</%s>\n", mLog); }
|
||||||
printf("</%s>\n", mLog);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *mLog;
|
const char *mLog;
|
||||||
};
|
};
|
||||||
@@ -157,21 +154,16 @@ struct RAIITracer {
|
|||||||
|
|
||||||
// Sets variable to value on creation then resets variable to its original
|
// Sets variable to value on creation then resets variable to its original
|
||||||
// value on destruction
|
// value on destruction
|
||||||
template<typename T>
|
template <typename T> class ValueRollback {
|
||||||
class ValueRollback {
|
|
||||||
public:
|
public:
|
||||||
template <typename U = T>
|
template <typename U = T>
|
||||||
ValueRollback(T &variable, U &&value)
|
ValueRollback(T &variable, U &&value)
|
||||||
: mVariable{&variable}
|
: mVariable{&variable},
|
||||||
, mSavedValue{std::exchange(variable, std::forward<U>(value))}
|
mSavedValue{std::exchange(variable, std::forward<U>(value))} {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueRollback(ValueRollback &&other) noexcept
|
ValueRollback(ValueRollback &&other) noexcept
|
||||||
: mVariable{std::exchange(other.mVariable, nullptr)}
|
: mVariable{std::exchange(other.mVariable, nullptr)},
|
||||||
, mSavedValue{std::move(other.mSavedValue)}
|
mSavedValue{std::move(other.mSavedValue)} {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueRollback(const ValueRollback &) = delete;
|
ValueRollback(const ValueRollback &) = delete;
|
||||||
ValueRollback &operator=(ValueRollback &&) = delete;
|
ValueRollback &operator=(ValueRollback &&) = delete;
|
||||||
@@ -227,7 +219,8 @@ struct FileInfo {
|
|||||||
struct MacroExpansionState {
|
struct MacroExpansionState {
|
||||||
Token MacroNameToken;
|
Token MacroNameToken;
|
||||||
const MacroInfo *MacroInfo = nullptr;
|
const MacroInfo *MacroInfo = nullptr;
|
||||||
std::vector<std::string> Dependencies; // other macro symbols this expansions depends on
|
// other macro symbols this expansion depends on
|
||||||
|
std::vector<std::string> Dependencies;
|
||||||
std::string Expansion;
|
std::string Expansion;
|
||||||
std::map<SourceLocation, unsigned> TokenLocations;
|
std::map<SourceLocation, unsigned> TokenLocations;
|
||||||
SourceRange Range;
|
SourceRange Range;
|
||||||
@@ -255,10 +248,8 @@ public:
|
|||||||
FileID PrevFID) override;
|
FileID PrevFID) override;
|
||||||
|
|
||||||
virtual void InclusionDirective(SourceLocation HashLoc,
|
virtual void InclusionDirective(SourceLocation HashLoc,
|
||||||
const Token &IncludeTok,
|
const Token &IncludeTok, StringRef FileName,
|
||||||
StringRef FileName,
|
bool IsAngled, CharSourceRange FileNameRange,
|
||||||
bool IsAngled,
|
|
||||||
CharSourceRange FileNameRange,
|
|
||||||
#if CLANG_VERSION_MAJOR >= 16
|
#if CLANG_VERSION_MAJOR >= 16
|
||||||
OptionalFileEntryRef File,
|
OptionalFileEntryRef File,
|
||||||
#elif CLANG_VERSION_MAJOR >= 15
|
#elif CLANG_VERSION_MAJOR >= 15
|
||||||
@@ -266,8 +257,7 @@ public:
|
|||||||
#else
|
#else
|
||||||
const FileEntry *File,
|
const FileEntry *File,
|
||||||
#endif
|
#endif
|
||||||
StringRef SearchPath,
|
StringRef SearchPath, StringRef RelativePath,
|
||||||
StringRef RelativePath,
|
|
||||||
#if CLANG_VERSION_MAJOR >= 19
|
#if CLANG_VERSION_MAJOR >= 19
|
||||||
const Module *SuggestedModule,
|
const Module *SuggestedModule,
|
||||||
bool ModuleImported,
|
bool ModuleImported,
|
||||||
@@ -314,9 +304,11 @@ private:
|
|||||||
// Tracks the set of declarations that the current expression/statement is
|
// Tracks the set of declarations that the current expression/statement is
|
||||||
// nested inside of.
|
// nested inside of.
|
||||||
struct AutoSetContext {
|
struct AutoSetContext {
|
||||||
AutoSetContext(IndexConsumer *Self, NamedDecl *Context, bool VisitImplicit = false)
|
AutoSetContext(IndexConsumer *Self, NamedDecl *Context,
|
||||||
|
bool VisitImplicit = false)
|
||||||
: Self(Self), Prev(Self->CurDeclContext), Decl(Context) {
|
: Self(Self), Prev(Self->CurDeclContext), Decl(Context) {
|
||||||
this->VisitImplicit = VisitImplicit || (Prev ? Prev->VisitImplicit : false);
|
this->VisitImplicit =
|
||||||
|
VisitImplicit || (Prev ? Prev->VisitImplicit : false);
|
||||||
Self->CurDeclContext = this;
|
Self->CurDeclContext = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,7 +445,8 @@ private:
|
|||||||
if (IsInvalid) {
|
if (IsInvalid) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
unsigned Column1 = SM.getColumnNumber(Begin.first, Begin.second, &IsInvalid);
|
unsigned Column1 =
|
||||||
|
SM.getColumnNumber(Begin.first, Begin.second, &IsInvalid);
|
||||||
if (IsInvalid) {
|
if (IsInvalid) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -496,8 +489,8 @@ private:
|
|||||||
std::string Backing;
|
std::string Backing;
|
||||||
llvm::raw_string_ostream Stream(Backing);
|
llvm::raw_string_ostream Stream(Backing);
|
||||||
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
|
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
|
||||||
printTemplateArgumentList(
|
printTemplateArgumentList(Stream, TemplateArgs.asArray(),
|
||||||
Stream, TemplateArgs.asArray(), PrintingPolicy(CI.getLangOpts()));
|
PrintingPolicy(CI.getLangOpts()));
|
||||||
Result += Stream.str();
|
Result += Stream.str();
|
||||||
}
|
}
|
||||||
} else if (const auto *Nd = dyn_cast<NamespaceDecl>(DC)) {
|
} else if (const auto *Nd = dyn_cast<NamespaceDecl>(DC)) {
|
||||||
@@ -549,7 +542,8 @@ private:
|
|||||||
// we can end up with hash collisions where different symbols from
|
// we can end up with hash collisions where different symbols from
|
||||||
// different platforms map to the same thing.
|
// different platforms map to the same thing.
|
||||||
char *Platform = getenv("MOZSEARCH_PLATFORM");
|
char *Platform = getenv("MOZSEARCH_PLATFORM");
|
||||||
Filename = std::string(Platform ? Platform : "") + std::string("@") + Filename;
|
Filename =
|
||||||
|
std::string(Platform ? Platform : "") + std::string("@") + Filename;
|
||||||
}
|
}
|
||||||
return hash(Filename + std::string("@") + locationToString(Loc));
|
return hash(Filename + std::string("@") + locationToString(Loc));
|
||||||
}
|
}
|
||||||
@@ -569,8 +563,8 @@ private:
|
|||||||
// The majority of path characters are letters and slashes which don't get
|
// The majority of path characters are letters and slashes which don't get
|
||||||
// encoded, so that satisfies (1). Since "@" characters in the unsanitized
|
// encoded, so that satisfies (1). Since "@" characters in the unsanitized
|
||||||
// path get encoded, there should be no "@" characters in the sanitized path
|
// path get encoded, there should be no "@" characters in the sanitized path
|
||||||
// that got preserved from the unsanitized input, so that should satisfy (2).
|
// that got preserved from the unsanitized input, so that should satisfy
|
||||||
// And (3) was done by trial-and-error. Note in particular the dot (.)
|
// (2). And (3) was done by trial-and-error. Note in particular the dot (.)
|
||||||
// character needs to be encoded, or the symbol-search feature of mozsearch
|
// character needs to be encoded, or the symbol-search feature of mozsearch
|
||||||
// doesn't work correctly, as all dot characters in the symbol query get
|
// doesn't work correctly, as all dot characters in the symbol query get
|
||||||
// replaced by #.
|
// replaced by #.
|
||||||
@@ -591,7 +585,8 @@ private:
|
|||||||
// we can end up with hash collisions where different symbols from
|
// we can end up with hash collisions where different symbols from
|
||||||
// different platforms map to the same thing.
|
// different platforms map to the same thing.
|
||||||
char *Platform = getenv("MOZSEARCH_PLATFORM");
|
char *Platform = getenv("MOZSEARCH_PLATFORM");
|
||||||
Filename = std::string(Platform ? Platform : "") + std::string("@") + Filename;
|
Filename =
|
||||||
|
std::string(Platform ? Platform : "") + std::string("@") + Filename;
|
||||||
}
|
}
|
||||||
return Filename;
|
return Filename;
|
||||||
}
|
}
|
||||||
@@ -708,11 +703,11 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
IndexConsumer(CompilerInstance &CI)
|
IndexConsumer(CompilerInstance &CI)
|
||||||
: CI(CI), SM(CI.getSourceManager()), LO(CI.getLangOpts()), CurMangleContext(nullptr),
|
: CI(CI), SM(CI.getSourceManager()), LO(CI.getLangOpts()),
|
||||||
AstContext(nullptr), ConcatInfo(CI.getPreprocessor()), CurDeclContext(nullptr),
|
CurMangleContext(nullptr), AstContext(nullptr),
|
||||||
|
ConcatInfo(CI.getPreprocessor()), CurDeclContext(nullptr),
|
||||||
TemplateStack(nullptr) {
|
TemplateStack(nullptr) {
|
||||||
CI.getPreprocessor().addPPCallbacks(
|
CI.getPreprocessor().addPPCallbacks(make_unique<PreprocessorHook>(this));
|
||||||
make_unique<PreprocessorHook>(this));
|
|
||||||
CI.getPreprocessor().setTokenWatcher(
|
CI.getPreprocessor().setTokenWatcher(
|
||||||
[this](const auto &token) { onTokenLexed(token); });
|
[this](const auto &token) { onTokenLexed(token); });
|
||||||
}
|
}
|
||||||
@@ -757,8 +752,8 @@ public:
|
|||||||
FileInfo &Info = *It->second;
|
FileInfo &Info = *It->second;
|
||||||
|
|
||||||
std::string Filename = Outdir + Info.Realname;
|
std::string Filename = Outdir + Info.Realname;
|
||||||
std::string SrcFilename = Info.Generated
|
std::string SrcFilename =
|
||||||
? Objdir + Info.Realname.substr(GENERATED.length())
|
Info.Generated ? Objdir + Info.Realname.substr(GENERATED.length())
|
||||||
: Srcdir + PATHSEP_STRING + Info.Realname;
|
: Srcdir + PATHSEP_STRING + Info.Realname;
|
||||||
|
|
||||||
ensurePath(Filename);
|
ensurePath(Filename);
|
||||||
@@ -778,13 +773,15 @@ public:
|
|||||||
std::ifstream Fin(Filename.c_str(), std::ios::in | std::ios::binary);
|
std::ifstream Fin(Filename.c_str(), std::ios::in | std::ios::binary);
|
||||||
FILE *OutFp = Lock.openTmp();
|
FILE *OutFp = Lock.openTmp();
|
||||||
if (!OutFp) {
|
if (!OutFp) {
|
||||||
fprintf(stderr, "Unable to open tmp out file for %s\n", Filename.c_str());
|
fprintf(stderr, "Unable to open tmp out file for %s\n",
|
||||||
|
Filename.c_str());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort our new results and get an iterator to them
|
// Sort our new results and get an iterator to them
|
||||||
std::sort(Info.Output.begin(), Info.Output.end());
|
std::sort(Info.Output.begin(), Info.Output.end());
|
||||||
std::vector<std::string>::const_iterator NewLinesIter = Info.Output.begin();
|
std::vector<std::string>::const_iterator NewLinesIter =
|
||||||
|
Info.Output.begin();
|
||||||
std::string LastNewWritten;
|
std::string LastNewWritten;
|
||||||
|
|
||||||
// Loop over the existing (sorted) lines in the analysis output file.
|
// Loop over the existing (sorted) lines in the analysis output file.
|
||||||
@@ -815,8 +812,10 @@ public:
|
|||||||
// dedupe the new entries being written
|
// dedupe the new entries being written
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (fwrite(NewLinesIter->c_str(), NewLinesIter->length(), 1, OutFp) != 1) {
|
if (fwrite(NewLinesIter->c_str(), NewLinesIter->length(), 1, OutFp) !=
|
||||||
fprintf(stderr, "Unable to write %zu bytes[1] to tmp output file for %s\n",
|
1) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Unable to write %zu bytes[1] to tmp output file for %s\n",
|
||||||
NewLinesIter->length(), Filename.c_str());
|
NewLinesIter->length(), Filename.c_str());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -825,7 +824,8 @@ public:
|
|||||||
|
|
||||||
// Write the entry read from the existing file.
|
// Write the entry read from the existing file.
|
||||||
if (fwrite(OldLine.c_str(), OldLine.length(), 1, OutFp) != 1) {
|
if (fwrite(OldLine.c_str(), OldLine.length(), 1, OutFp) != 1) {
|
||||||
fprintf(stderr, "Unable to write %zu bytes[2] to tmp output file for %s\n",
|
fprintf(stderr,
|
||||||
|
"Unable to write %zu bytes[2] to tmp output file for %s\n",
|
||||||
OldLine.length(), Filename.c_str());
|
OldLine.length(), Filename.c_str());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -839,8 +839,10 @@ public:
|
|||||||
if (*NewLinesIter == LastNewWritten) {
|
if (*NewLinesIter == LastNewWritten) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (fwrite(NewLinesIter->c_str(), NewLinesIter->length(), 1, OutFp) != 1) {
|
if (fwrite(NewLinesIter->c_str(), NewLinesIter->length(), 1, OutFp) !=
|
||||||
fprintf(stderr, "Unable to write %zu bytes[3] to tmp output file for %s\n",
|
1) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Unable to write %zu bytes[3] to tmp output file for %s\n",
|
||||||
NewLinesIter->length(), Filename.c_str());
|
NewLinesIter->length(), Filename.c_str());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -851,7 +853,9 @@ public:
|
|||||||
// with the new one.
|
// with the new one.
|
||||||
fclose(OutFp);
|
fclose(OutFp);
|
||||||
if (!Lock.moveTmp()) {
|
if (!Lock.moveTmp()) {
|
||||||
fprintf(stderr, "Unable to move tmp output file into place for %s (err %d)\n", Filename.c_str(), errno);
|
fprintf(stderr,
|
||||||
|
"Unable to move tmp output file into place for %s (err %d)\n",
|
||||||
|
Filename.c_str(), errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -950,7 +954,8 @@ public:
|
|||||||
D = F->getTemplateInstantiationPattern();
|
D = F->getTemplateInstantiationPattern();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Context(D->getQualifiedNameAsString(), getMangledName(CurMangleContext, D));
|
return Context(D->getQualifiedNameAsString(),
|
||||||
|
getMangledName(CurMangleContext, D));
|
||||||
}
|
}
|
||||||
|
|
||||||
Context getContext(SourceLocation Loc) {
|
Context getContext(SourceLocation Loc) {
|
||||||
@@ -990,7 +995,8 @@ public:
|
|||||||
return Context();
|
return Context();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Searches for the closest CurDeclContext parent that is a function template instantiation
|
// Searches for the closest CurDeclContext parent that is a function template
|
||||||
|
// instantiation
|
||||||
const FunctionDecl *getCurrentFunctionTemplateInstantiation() {
|
const FunctionDecl *getCurrentFunctionTemplateInstantiation() {
|
||||||
const auto *Ctxt = CurDeclContext;
|
const auto *Ctxt = CurDeclContext;
|
||||||
while (Ctxt) {
|
while (Ctxt) {
|
||||||
@@ -1033,9 +1039,9 @@ public:
|
|||||||
// indexer to visit EVERY identifier, which is way too much data.
|
// indexer to visit EVERY identifier, which is way too much data.
|
||||||
struct AutoTemplateContext {
|
struct AutoTemplateContext {
|
||||||
AutoTemplateContext(IndexConsumer *Self)
|
AutoTemplateContext(IndexConsumer *Self)
|
||||||
: Self(Self)
|
: Self(Self), CurMode(Self->TemplateStack ? Self->TemplateStack->CurMode
|
||||||
, CurMode(Self->TemplateStack ? Self->TemplateStack->CurMode : Mode::GatherDependent)
|
: Mode::GatherDependent),
|
||||||
, Parent(Self->TemplateStack) {
|
Parent(Self->TemplateStack) {
|
||||||
Self->TemplateStack = this;
|
Self->TemplateStack = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1066,9 +1072,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inGatherMode() {
|
bool inGatherMode() { return CurMode == Mode::GatherDependent; }
|
||||||
return CurMode == Mode::GatherDependent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do we need to perform the extra AnalyzeDependent passes (one per
|
// Do we need to perform the extra AnalyzeDependent passes (one per
|
||||||
// instantiation)?
|
// instantiation)?
|
||||||
@@ -1119,7 +1123,8 @@ public:
|
|||||||
|
|
||||||
AutoTemplateContext *TemplateStack;
|
AutoTemplateContext *TemplateStack;
|
||||||
|
|
||||||
std::unordered_multimap<const FunctionDecl *, const Stmt *> ForwardingTemplates;
|
std::unordered_multimap<const FunctionDecl *, const Stmt *>
|
||||||
|
ForwardingTemplates;
|
||||||
std::unordered_set<unsigned> ForwardedTemplateLocations;
|
std::unordered_set<unsigned> ForwardedTemplateLocations;
|
||||||
|
|
||||||
bool shouldVisitTemplateInstantiations() const {
|
bool shouldVisitTemplateInstantiations() const {
|
||||||
@@ -1196,7 +1201,8 @@ public:
|
|||||||
// Flag to omit the identifier from being cross-referenced across files.
|
// Flag to omit the identifier from being cross-referenced across files.
|
||||||
// This is usually desired for local variables.
|
// This is usually desired for local variables.
|
||||||
NoCrossref = 1 << 0,
|
NoCrossref = 1 << 0,
|
||||||
// Flag to indicate the token with analysis data is not an identifier. Indicates
|
// Flag to indicate the token with analysis data is not an identifier.
|
||||||
|
// Indicates
|
||||||
// we want to skip the check that tries to ensure a sane identifier token.
|
// we want to skip the check that tries to ensure a sane identifier token.
|
||||||
NotIdentifierToken = 1 << 1,
|
NotIdentifierToken = 1 << 1,
|
||||||
// This indicates that the end of the provided SourceRange is valid and
|
// This indicates that the end of the provided SourceRange is valid and
|
||||||
@@ -1206,8 +1212,10 @@ public:
|
|||||||
LocRangeEndValid = 1 << 2
|
LocRangeEndValid = 1 << 2
|
||||||
};
|
};
|
||||||
|
|
||||||
void emitStructuredRecordInfo(llvm::json::OStream &J, SourceLocation Loc, const RecordDecl *decl) {
|
void emitStructuredRecordInfo(llvm::json::OStream &J, SourceLocation Loc,
|
||||||
J.attribute("kind", TypeWithKeyword::getTagTypeKindName(decl->getTagKind()));
|
const RecordDecl *decl) {
|
||||||
|
J.attribute("kind",
|
||||||
|
TypeWithKeyword::getTagTypeKindName(decl->getTagKind()));
|
||||||
|
|
||||||
const ASTContext &C = *AstContext;
|
const ASTContext &C = *AstContext;
|
||||||
const ASTRecordLayout &Layout = C.getASTRecordLayout(decl);
|
const ASTRecordLayout &Layout = C.getASTRecordLayout(decl);
|
||||||
@@ -1226,7 +1234,8 @@ public:
|
|||||||
// * the size string 4/8 is shorter than true/false in the analysis
|
// * the size string 4/8 is shorter than true/false in the analysis
|
||||||
// file
|
// file
|
||||||
const QualType ptrType = C.getUIntPtrType();
|
const QualType ptrType = C.getUIntPtrType();
|
||||||
J.attribute("ownVFPtrBytes", C.getTypeSizeInChars(ptrType).getQuantity());
|
J.attribute("ownVFPtrBytes",
|
||||||
|
C.getTypeSizeInChars(ptrType).getQuantity());
|
||||||
}
|
}
|
||||||
|
|
||||||
J.attributeBegin("supers");
|
J.attributeBegin("supers");
|
||||||
@@ -1310,14 +1319,17 @@ public:
|
|||||||
J.arrayBegin();
|
J.arrayBegin();
|
||||||
uint64_t iField = 0;
|
uint64_t iField = 0;
|
||||||
for (RecordDecl::field_iterator It = decl->field_begin(),
|
for (RecordDecl::field_iterator It = decl->field_begin(),
|
||||||
End = decl->field_end(); It != End; ++It, ++iField) {
|
End = decl->field_end();
|
||||||
|
It != End; ++It, ++iField) {
|
||||||
const FieldDecl &Field = **It;
|
const FieldDecl &Field = **It;
|
||||||
auto sourceRange = SM.getExpansionRange(Field.getSourceRange()).getAsRange();
|
auto sourceRange =
|
||||||
|
SM.getExpansionRange(Field.getSourceRange()).getAsRange();
|
||||||
uint64_t localOffsetBits = Layout.getFieldOffset(iField);
|
uint64_t localOffsetBits = Layout.getFieldOffset(iField);
|
||||||
CharUnits localOffsetBytes = C.toCharUnitsFromBits(localOffsetBits);
|
CharUnits localOffsetBytes = C.toCharUnitsFromBits(localOffsetBits);
|
||||||
|
|
||||||
J.objectBegin();
|
J.objectBegin();
|
||||||
J.attribute("lineRange", pathAndLineRangeToString(structFileID, sourceRange));
|
J.attribute("lineRange",
|
||||||
|
pathAndLineRangeToString(structFileID, sourceRange));
|
||||||
J.attribute("pretty", getQualifiedName(&Field));
|
J.attribute("pretty", getQualifiedName(&Field));
|
||||||
J.attribute("sym", getMangledName(CurMangleContext, &Field));
|
J.attribute("sym", getMangledName(CurMangleContext, &Field));
|
||||||
|
|
||||||
@@ -1346,7 +1358,8 @@ public:
|
|||||||
J.attributeBegin("bitPositions");
|
J.attributeBegin("bitPositions");
|
||||||
J.objectBegin();
|
J.objectBegin();
|
||||||
|
|
||||||
J.attribute("begin", unsigned(localOffsetBits - C.toBits(localOffsetBytes)));
|
J.attribute("begin",
|
||||||
|
unsigned(localOffsetBits - C.toBits(localOffsetBytes)));
|
||||||
J.attribute("width", Field.getBitWidthValue(C));
|
J.attribute("width", Field.getBitWidthValue(C));
|
||||||
|
|
||||||
J.objectEnd();
|
J.objectEnd();
|
||||||
@@ -1381,7 +1394,8 @@ public:
|
|||||||
J.attribute("kind", "enumConstant");
|
J.attribute("kind", "enumConstant");
|
||||||
}
|
}
|
||||||
|
|
||||||
void emitStructuredFunctionInfo(llvm::json::OStream &J, const FunctionDecl *decl) {
|
void emitStructuredFunctionInfo(llvm::json::OStream &J,
|
||||||
|
const FunctionDecl *decl) {
|
||||||
emitBindingAttributes(J, *decl);
|
emitBindingAttributes(J, *decl);
|
||||||
|
|
||||||
J.attributeBegin("args");
|
J.attributeBegin("args");
|
||||||
@@ -1431,7 +1445,8 @@ public:
|
|||||||
// TODO: Make sure we're doing template traversals appropriately...
|
// TODO: Make sure we're doing template traversals appropriately...
|
||||||
// findOverriddenMethods (now removed) liked to do:
|
// findOverriddenMethods (now removed) liked to do:
|
||||||
// if (Decl->isTemplateInstantiation()) {
|
// if (Decl->isTemplateInstantiation()) {
|
||||||
// Decl = dyn_cast<CXXMethodDecl>(Decl->getTemplateInstantiationPattern());
|
// Decl =
|
||||||
|
// dyn_cast<CXXMethodDecl>(Decl->getTemplateInstantiationPattern());
|
||||||
// }
|
// }
|
||||||
// I think our pre-emptive dereferencing/avoidance of templates may
|
// I think our pre-emptive dereferencing/avoidance of templates may
|
||||||
// protect us from this, but it needs more investigation.
|
// protect us from this, but it needs more investigation.
|
||||||
@@ -1507,7 +1522,8 @@ public:
|
|||||||
* Emit structured info for a variable if it is a static class member.
|
* Emit structured info for a variable if it is a static class member.
|
||||||
*/
|
*/
|
||||||
void emitStructuredVarInfo(llvm::json::OStream &J, const VarDecl *decl) {
|
void emitStructuredVarInfo(llvm::json::OStream &J, const VarDecl *decl) {
|
||||||
const auto *parentDecl = dyn_cast_or_null<RecordDecl>(decl->getDeclContext());
|
const auto *parentDecl =
|
||||||
|
dyn_cast_or_null<RecordDecl>(decl->getDeclContext());
|
||||||
|
|
||||||
J.attribute("kind", "field");
|
J.attribute("kind", "field");
|
||||||
|
|
||||||
@@ -1572,8 +1588,7 @@ public:
|
|||||||
// called for each identifier that corresponds to a symbol.
|
// called for each identifier that corresponds to a symbol.
|
||||||
void visitIdentifier(const char *Kind, const char *SyntaxKind,
|
void visitIdentifier(const char *Kind, const char *SyntaxKind,
|
||||||
llvm::StringRef QualName, SourceRange LocRange,
|
llvm::StringRef QualName, SourceRange LocRange,
|
||||||
std::string Symbol,
|
std::string Symbol, QualType MaybeType = QualType(),
|
||||||
QualType MaybeType = QualType(),
|
|
||||||
Context TokenContext = Context(), int Flags = 0,
|
Context TokenContext = Context(), int Flags = 0,
|
||||||
SourceRange PeekRange = SourceRange(),
|
SourceRange PeekRange = SourceRange(),
|
||||||
SourceRange NestingRange = SourceRange(),
|
SourceRange NestingRange = SourceRange(),
|
||||||
@@ -1583,7 +1598,9 @@ public:
|
|||||||
// Also visit the spelling site.
|
// Also visit the spelling site.
|
||||||
SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
|
SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
|
||||||
if (SpellingLoc != Loc) {
|
if (SpellingLoc != Loc) {
|
||||||
visitIdentifier(Kind, SyntaxKind, QualName, SpellingLoc, Symbol, MaybeType, TokenContext, Flags, PeekRange, NestingRange, ArgRanges);
|
visitIdentifier(Kind, SyntaxKind, QualName, SpellingLoc, Symbol,
|
||||||
|
MaybeType, TokenContext, Flags, PeekRange, NestingRange,
|
||||||
|
ArgRanges);
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
|
SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc);
|
||||||
@@ -1598,12 +1615,16 @@ public:
|
|||||||
|
|
||||||
// Find the file positions corresponding to the token.
|
// Find the file positions corresponding to the token.
|
||||||
unsigned StartOffset = SM.getFileOffset(ExpansionLoc);
|
unsigned StartOffset = SM.getFileOffset(ExpansionLoc);
|
||||||
unsigned EndOffset = (Flags & LocRangeEndValid)
|
unsigned EndOffset =
|
||||||
|
(Flags & LocRangeEndValid)
|
||||||
? SM.getFileOffset(LocRange.getEnd())
|
? SM.getFileOffset(LocRange.getEnd())
|
||||||
: StartOffset + Lexer::MeasureTokenLength(ExpansionLoc, SM, CI.getLangOpts());
|
: StartOffset +
|
||||||
|
Lexer::MeasureTokenLength(ExpansionLoc, SM, CI.getLangOpts());
|
||||||
|
|
||||||
std::string LocStr = locationToString(ExpansionLoc, EndOffset - StartOffset);
|
std::string LocStr =
|
||||||
std::string RangeStr = locationToString(ExpansionLoc, EndOffset - StartOffset);
|
locationToString(ExpansionLoc, EndOffset - StartOffset);
|
||||||
|
std::string RangeStr =
|
||||||
|
locationToString(ExpansionLoc, EndOffset - StartOffset);
|
||||||
std::string PeekRangeStr;
|
std::string PeekRangeStr;
|
||||||
|
|
||||||
if (!(Flags & NotIdentifierToken)) {
|
if (!(Flags & NotIdentifierToken)) {
|
||||||
@@ -1745,7 +1766,8 @@ public:
|
|||||||
J.objectBegin();
|
J.objectBegin();
|
||||||
J.attributeBegin(macroInfo.Key);
|
J.attributeBegin(macroInfo.Key);
|
||||||
J.objectBegin();
|
J.objectBegin();
|
||||||
J.attribute("", macroInfo.Expansion); // "" is the platform key, populated by the merge step
|
J.attribute("", macroInfo.Expansion); // "" is the platform key,
|
||||||
|
// populated by the merge step
|
||||||
J.objectEnd();
|
J.objectEnd();
|
||||||
J.attributeEnd();
|
J.attributeEnd();
|
||||||
J.objectEnd();
|
J.objectEnd();
|
||||||
@@ -1757,7 +1779,8 @@ public:
|
|||||||
J.objectBegin();
|
J.objectBegin();
|
||||||
J.attributeBegin(macroInfo.Key);
|
J.attributeBegin(macroInfo.Key);
|
||||||
J.objectBegin();
|
J.objectBegin();
|
||||||
J.attributeBegin(""); // "" is the platform key, populated by the merge step
|
J.attributeBegin(
|
||||||
|
""); // "" is the platform key, populated by the merge step
|
||||||
J.arrayBegin();
|
J.arrayBegin();
|
||||||
J.value(it->second);
|
J.value(it->second);
|
||||||
J.arrayEnd();
|
J.arrayEnd();
|
||||||
@@ -1815,7 +1838,8 @@ public:
|
|||||||
|
|
||||||
// But if there are parameters, we want to include those as well.
|
// But if there are parameters, we want to include those as well.
|
||||||
for (ParmVarDecl *Param : D->parameters()) {
|
for (ParmVarDecl *Param : D->parameters()) {
|
||||||
std::pair<FileID, unsigned> ParamLoc = SM.getDecomposedLoc(Param->getLocation());
|
std::pair<FileID, unsigned> ParamLoc =
|
||||||
|
SM.getDecomposedLoc(Param->getLocation());
|
||||||
|
|
||||||
// It's possible there are macros involved or something. We don't include
|
// It's possible there are macros involved or something. We don't include
|
||||||
// the parameters in that case.
|
// the parameters in that case.
|
||||||
@@ -1841,8 +1865,8 @@ public:
|
|||||||
for (CXXBaseSpecifier &Base : D2->bases()) {
|
for (CXXBaseSpecifier &Base : D2->bases()) {
|
||||||
std::pair<FileID, unsigned> Loc = SM.getDecomposedLoc(Base.getEndLoc());
|
std::pair<FileID, unsigned> Loc = SM.getDecomposedLoc(Base.getEndLoc());
|
||||||
|
|
||||||
// It's possible there are macros involved or something. We don't include
|
// It's possible there are macros involved or something. We don't
|
||||||
// the parameters in that case.
|
// include the parameters in that case.
|
||||||
if (Loc.first == FuncLoc.first) {
|
if (Loc.first == FuncLoc.first) {
|
||||||
// Assume parameters are in order, so we always take the last one.
|
// Assume parameters are in order, so we always take the last one.
|
||||||
End = Base.getEndLoc();
|
End = Base.getEndLoc();
|
||||||
@@ -1854,8 +1878,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
SourceRange getCommentRange(NamedDecl *D) {
|
SourceRange getCommentRange(NamedDecl *D) {
|
||||||
const RawComment* RC =
|
const RawComment *RC = AstContext->getRawCommentForDeclNoCache(D);
|
||||||
AstContext->getRawCommentForDeclNoCache(D);
|
|
||||||
if (!RC) {
|
if (!RC) {
|
||||||
return SourceRange();
|
return SourceRange();
|
||||||
}
|
}
|
||||||
@@ -1944,7 +1967,8 @@ public:
|
|||||||
D = D2->getTemplateInstantiationPattern();
|
D = D2->getTemplateInstantiationPattern();
|
||||||
}
|
}
|
||||||
// We treat pure virtual declarations as definitions.
|
// We treat pure virtual declarations as definitions.
|
||||||
Kind = (D2->isThisDeclarationADefinition() || isPure(D2)) ? "def" : "decl";
|
Kind =
|
||||||
|
(D2->isThisDeclarationADefinition() || isPure(D2)) ? "def" : "decl";
|
||||||
PrettyKind = "function";
|
PrettyKind = "function";
|
||||||
PeekRange = getFunctionPeekRange(D2);
|
PeekRange = getFunctionPeekRange(D2);
|
||||||
|
|
||||||
@@ -1998,7 +2022,8 @@ public:
|
|||||||
if (D2) {
|
if (D2) {
|
||||||
// There's no exposure of the left brace so we have to find it.
|
// There's no exposure of the left brace so we have to find it.
|
||||||
NestingRange = SourceRange(
|
NestingRange = SourceRange(
|
||||||
findLeftBraceFromLoc(D2->isAnonymousNamespace() ? D2->getBeginLoc() : ExpansionLoc),
|
findLeftBraceFromLoc(D2->isAnonymousNamespace() ? D2->getBeginLoc()
|
||||||
|
: ExpansionLoc),
|
||||||
D2->getRBraceLoc());
|
D2->getRBraceLoc());
|
||||||
}
|
}
|
||||||
} else if (isa<FieldDecl>(D)) {
|
} else if (isa<FieldDecl>(D)) {
|
||||||
@@ -2024,9 +2049,9 @@ public:
|
|||||||
|
|
||||||
// In the case of destructors, Loc might point to the ~ character. In that
|
// In the case of destructors, Loc might point to the ~ character. In that
|
||||||
// case we want to skip to the name of the class. However, Loc might also
|
// case we want to skip to the name of the class. However, Loc might also
|
||||||
// point to other places that generate destructors, such as a lambda (apparently
|
// point to other places that generate destructors, such as a lambda
|
||||||
// clang 8 creates a destructor declaration for at least some lambdas). In
|
// (apparently clang 8 creates a destructor declaration for at least some
|
||||||
// that case we'll just drop the declaration.
|
// lambdas). In that case we'll just drop the declaration.
|
||||||
if (isa<CXXDestructorDecl>(D)) {
|
if (isa<CXXDestructorDecl>(D)) {
|
||||||
PrettyKind = "destructor";
|
PrettyKind = "destructor";
|
||||||
const char *P = SM.getCharacterData(Loc);
|
const char *P = SM.getCharacterData(Loc);
|
||||||
@@ -2046,9 +2071,9 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
visitIdentifier(Kind, PrettyKind, getQualifiedName(D), SourceRange(Loc), Symbol,
|
visitIdentifier(Kind, PrettyKind, getQualifiedName(D), SourceRange(Loc),
|
||||||
qtype,
|
Symbol, qtype, getContext(D), Flags, PeekRange,
|
||||||
getContext(D), Flags, PeekRange, NestingRange);
|
NestingRange);
|
||||||
|
|
||||||
// In-progress structured info emission.
|
// In-progress structured info emission.
|
||||||
if (RecordDecl *D2 = dyn_cast<RecordDecl>(D)) {
|
if (RecordDecl *D2 = dyn_cast<RecordDecl>(D)) {
|
||||||
@@ -2058,8 +2083,7 @@ public:
|
|||||||
// dependent type or if we're in any kind of template context. This
|
// dependent type or if we're in any kind of template context. This
|
||||||
// should be re-evaluated once this is working for normal classes and
|
// should be re-evaluated once this is working for normal classes and
|
||||||
// we can better evaluate what is useful.
|
// we can better evaluate what is useful.
|
||||||
!D2->isDependentType() &&
|
!D2->isDependentType() && !TemplateStack) {
|
||||||
!TemplateStack) {
|
|
||||||
if (auto *D3 = dyn_cast<CXXRecordDecl>(D2)) {
|
if (auto *D3 = dyn_cast<CXXRecordDecl>(D2)) {
|
||||||
findBindingToJavaClass(*AstContext, *D3);
|
findBindingToJavaClass(*AstContext, *D3);
|
||||||
findBoundAsJavaClasses(*AstContext, *D3);
|
findBoundAsJavaClasses(*AstContext, *D3);
|
||||||
@@ -2082,10 +2106,8 @@ public:
|
|||||||
if ((D2->isThisDeclarationADefinition() || isPure(D2)) &&
|
if ((D2->isThisDeclarationADefinition() || isPure(D2)) &&
|
||||||
// a clause at the top should have generalized and set wasTemplate so
|
// a clause at the top should have generalized and set wasTemplate so
|
||||||
// it shouldn't be the case that isTemplateInstantiation() is true.
|
// it shouldn't be the case that isTemplateInstantiation() is true.
|
||||||
!D2->isTemplateInstantiation() &&
|
!D2->isTemplateInstantiation() && !wasTemplate &&
|
||||||
!wasTemplate &&
|
!D2->isFunctionTemplateSpecialization() && !TemplateStack) {
|
||||||
!D2->isFunctionTemplateSpecialization() &&
|
|
||||||
!TemplateStack) {
|
|
||||||
if (auto *D3 = dyn_cast<CXXMethodDecl>(D2)) {
|
if (auto *D3 = dyn_cast<CXXMethodDecl>(D2)) {
|
||||||
findBindingToJavaMember(*AstContext, *D3);
|
findBindingToJavaMember(*AstContext, *D3);
|
||||||
} else {
|
} else {
|
||||||
@@ -2095,14 +2117,12 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (FieldDecl *D2 = dyn_cast<FieldDecl>(D)) {
|
if (FieldDecl *D2 = dyn_cast<FieldDecl>(D)) {
|
||||||
if (!D2->isTemplated() &&
|
if (!D2->isTemplated() && !TemplateStack) {
|
||||||
!TemplateStack) {
|
|
||||||
emitStructuredInfo(ExpansionLoc, D2);
|
emitStructuredInfo(ExpansionLoc, D2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (VarDecl *D2 = dyn_cast<VarDecl>(D)) {
|
if (VarDecl *D2 = dyn_cast<VarDecl>(D)) {
|
||||||
if (!D2->isTemplated() &&
|
if (!D2->isTemplated() && !TemplateStack &&
|
||||||
!TemplateStack &&
|
|
||||||
isa<CXXRecordDecl>(D2->getDeclContext())) {
|
isa<CXXRecordDecl>(D2->getDeclContext())) {
|
||||||
findBindingToJavaConstant(*AstContext, *D2);
|
findBindingToJavaConstant(*AstContext, *D2);
|
||||||
emitStructuredInfo(ExpansionLoc, D2);
|
emitStructuredInfo(ExpansionLoc, D2);
|
||||||
@@ -2118,11 +2138,14 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are in a template and find a Stmt that was registed in ForwardedTemplateLocations,
|
// If we are in a template and find a Stmt that was registed in
|
||||||
// convert the location to an actual Stmt* in ForwardingTemplates
|
// ForwardedTemplateLocations, convert the location to an actual Stmt* in
|
||||||
|
// ForwardingTemplates
|
||||||
if (TemplateStack && !TemplateStack->inGatherMode()) {
|
if (TemplateStack && !TemplateStack->inGatherMode()) {
|
||||||
if (ForwardedTemplateLocations.find(E->getBeginLoc().getRawEncoding()) != ForwardedTemplateLocations.end()) {
|
if (ForwardedTemplateLocations.find(E->getBeginLoc().getRawEncoding()) !=
|
||||||
ForwardingTemplates.insert({getCurrentFunctionTemplateInstantiation(), E});
|
ForwardedTemplateLocations.end()) {
|
||||||
|
ForwardingTemplates.insert(
|
||||||
|
{getCurrentFunctionTemplateInstantiation(), E});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2148,8 +2171,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
|
bool VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
|
||||||
// If we are in a template and the callee is type-dependent, register it in ForwardedTemplateLocations
|
// If we are in a template and the callee is type-dependent, register it in
|
||||||
// to forward its uses to the surrounding template call site
|
// ForwardedTemplateLocations to forward its uses to the surrounding
|
||||||
|
// template call site
|
||||||
if (TemplateStack && TemplateStack->inGatherMode()) {
|
if (TemplateStack && TemplateStack->inGatherMode()) {
|
||||||
if (E->isTypeDependent()) {
|
if (E->isTypeDependent()) {
|
||||||
TemplateStack->visitDependent(E->getBeginLoc());
|
TemplateStack->visitDependent(E->getBeginLoc());
|
||||||
@@ -2210,9 +2234,10 @@ public:
|
|||||||
argRanges.push_back(argExpr->getSourceRange());
|
argRanges.push_back(argExpr->getSourceRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
visitIdentifier("use", "function", getQualifiedName(NamedCallee), Loc, Mangled,
|
visitIdentifier("use", "function", getQualifiedName(NamedCallee), Loc,
|
||||||
E->getCallReturnType(*AstContext), getContext(SpellingLoc), Flags,
|
Mangled, E->getCallReturnType(*AstContext),
|
||||||
SourceRange(), SourceRange(), &argRanges);
|
getContext(SpellingLoc), Flags, SourceRange(),
|
||||||
|
SourceRange(), &argRanges);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2300,7 +2325,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VisitForwardedStatements(const Expr *E, SourceLocation Loc) {
|
void VisitForwardedStatements(const Expr *E, SourceLocation Loc) {
|
||||||
// If this is a forwarding template (eg MakeUnique), visit the forwarded statements
|
// If this is a forwarding template (eg MakeUnique), visit the forwarded
|
||||||
|
// statements
|
||||||
auto todo = std::stack{std::vector<const Stmt *>{E}};
|
auto todo = std::stack{std::vector<const Stmt *>{E}};
|
||||||
auto seen = std::unordered_set<const Stmt *>{};
|
auto seen = std::unordered_set<const Stmt *>{};
|
||||||
while (!todo.empty()) {
|
while (!todo.empty()) {
|
||||||
@@ -2326,8 +2352,10 @@ public:
|
|||||||
continue;
|
continue;
|
||||||
if (!F->isTemplateInstantiation())
|
if (!F->isTemplateInstantiation())
|
||||||
continue;
|
continue;
|
||||||
const auto [ForwardedBegin, ForwardedEnd] = ForwardingTemplates.equal_range(F);
|
const auto [ForwardedBegin, ForwardedEnd] =
|
||||||
for (auto ForwardedIt = ForwardedBegin; ForwardedIt != ForwardedEnd; ++ForwardedIt)
|
ForwardingTemplates.equal_range(F);
|
||||||
|
for (auto ForwardedIt = ForwardedBegin; ForwardedIt != ForwardedEnd;
|
||||||
|
++ForwardedIt)
|
||||||
if (seen.find(ForwardedIt->second) == seen.end())
|
if (seen.find(ForwardedIt->second) == seen.end())
|
||||||
todo.push(ForwardedIt->second);
|
todo.push(ForwardedIt->second);
|
||||||
}
|
}
|
||||||
@@ -2339,12 +2367,16 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are in a template and find a Stmt that was registed in ForwardedTemplateLocations,
|
// If we are in a template and find a Stmt that was registed in
|
||||||
// convert the location to an actual Stmt* in ForwardingTemplates
|
// ForwardedTemplateLocations, convert the location to an actual Stmt* in
|
||||||
|
// ForwardingTemplates
|
||||||
if (TemplateStack && !TemplateStack->inGatherMode()) {
|
if (TemplateStack && !TemplateStack->inGatherMode()) {
|
||||||
const auto IsForwarded = ForwardedTemplateLocations.find(E->getBeginLoc().getRawEncoding()) != ForwardedTemplateLocations.end();
|
const auto IsForwarded =
|
||||||
|
ForwardedTemplateLocations.find(E->getBeginLoc().getRawEncoding()) !=
|
||||||
|
ForwardedTemplateLocations.end();
|
||||||
if (IsForwarded) {
|
if (IsForwarded) {
|
||||||
ForwardingTemplates.insert({getCurrentFunctionTemplateInstantiation(), E});
|
ForwardingTemplates.insert(
|
||||||
|
{getCurrentFunctionTemplateInstantiation(), E});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2513,8 +2545,9 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are in a template and the new is type-dependent, register it in ForwardedTemplateLocations
|
// If we are in a template and the new is type-dependent, register it in
|
||||||
// to forward its uses to the surrounding template call site
|
// ForwardedTemplateLocations to forward its uses to the surrounding
|
||||||
|
// template call site
|
||||||
if (TemplateStack && TemplateStack->inGatherMode()) {
|
if (TemplateStack && TemplateStack->inGatherMode()) {
|
||||||
const auto *TypeInfo = N->getAllocatedTypeSourceInfo();
|
const auto *TypeInfo = N->getAllocatedTypeSourceInfo();
|
||||||
const auto ConstructExprLoc = TypeInfo->getTypeLoc().getBeginLoc();
|
const auto ConstructExprLoc = TypeInfo->getTypeLoc().getBeginLoc();
|
||||||
@@ -2544,7 +2577,8 @@ public:
|
|||||||
|
|
||||||
// Also record the dependent NestedNameSpecifier locations
|
// Also record the dependent NestedNameSpecifier locations
|
||||||
for (auto NestedNameLoc = E->getQualifierLoc();
|
for (auto NestedNameLoc = E->getQualifierLoc();
|
||||||
NestedNameLoc && NestedNameLoc.getNestedNameSpecifier()->isDependent();
|
NestedNameLoc &&
|
||||||
|
NestedNameLoc.getNestedNameSpecifier()->isDependent();
|
||||||
NestedNameLoc = NestedNameLoc.getPrefix()) {
|
NestedNameLoc = NestedNameLoc.getPrefix()) {
|
||||||
TemplateStack->visitDependent(NestedNameLoc.getLocalBeginLoc());
|
TemplateStack->visitDependent(NestedNameLoc.getLocalBeginLoc());
|
||||||
}
|
}
|
||||||
@@ -2575,9 +2609,8 @@ public:
|
|||||||
|
|
||||||
std::string symbol = std::string("URL_") + mangleURL(s);
|
std::string symbol = std::string("URL_") + mangleURL(s);
|
||||||
|
|
||||||
visitIdentifier("use", "file", StringRef(s), Loc, symbol,
|
visitIdentifier("use", "file", StringRef(s), Loc, symbol, QualType(),
|
||||||
QualType(), Context(),
|
Context(), NotIdentifierToken | LocRangeEndValid);
|
||||||
NotIdentifierToken | LocRangeEndValid);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2592,11 +2625,11 @@ public:
|
|||||||
std::string symbol =
|
std::string symbol =
|
||||||
std::string("FILE_") + mangleFile(newFile->Realname, type);
|
std::string("FILE_") + mangleFile(newFile->Realname, type);
|
||||||
|
|
||||||
// We use an explicit zero-length source range at the start of the file. If we
|
// We use an explicit zero-length source range at the start of the file. If
|
||||||
// don't set the LocRangeEndValid flag, the visitIdentifier code will use the
|
// we don't set the LocRangeEndValid flag, the visitIdentifier code will use
|
||||||
// entire first token, which could be e.g. a long multiline-comment.
|
// the entire first token, which could be e.g. a long multiline-comment.
|
||||||
visitIdentifier("def", "file", newFile->Realname, SourceRange(Loc),
|
visitIdentifier("def", "file", newFile->Realname, SourceRange(Loc), symbol,
|
||||||
symbol, QualType(), Context(),
|
QualType(), Context(),
|
||||||
NotIdentifierToken | LocRangeEndValid);
|
NotIdentifierToken | LocRangeEndValid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2606,17 +2639,19 @@ public:
|
|||||||
if (type == FileType::Unknown) {
|
if (type == FileType::Unknown) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::string symbol =
|
std::string symbol = std::string("FILE_") + mangleFile(includedFile, type);
|
||||||
std::string("FILE_") + mangleFile(includedFile, type);
|
|
||||||
|
|
||||||
// Support the #include MACRO use-case
|
// Support the #include MACRO use-case
|
||||||
// When parsing #include MACRO:
|
// When parsing #include MACRO:
|
||||||
// - the filename is never passed to onTokenLexed
|
// - the filename is never passed to onTokenLexed
|
||||||
// - inclusionDirective is called before endMacroExpansion (which is only called when the following token is parsed)
|
// - inclusionDirective is called before endMacroExpansion (which is only
|
||||||
// So add the filename here and call endMacroExpansion immediately.
|
// called when the following token is parsed) So add the filename here and
|
||||||
// This ensures the macro has a correct expansion and it has been added to MacroMaps so the referenced filename knows to populate inExpansionAt.
|
// call endMacroExpansion immediately. This ensures the macro has a correct
|
||||||
|
// expansion and it has been added to MacroMaps so the referenced filename
|
||||||
|
// knows to populate inExpansionAt.
|
||||||
if (MacroExpansionState) {
|
if (MacroExpansionState) {
|
||||||
MacroExpansionState->TokenLocations[FileNameRange.getBegin()] = MacroExpansionState->Expansion.length();
|
MacroExpansionState->TokenLocations[FileNameRange.getBegin()] =
|
||||||
|
MacroExpansionState->Expansion.length();
|
||||||
MacroExpansionState->Expansion += '"';
|
MacroExpansionState->Expansion += '"';
|
||||||
MacroExpansionState->Expansion += includedFile;
|
MacroExpansionState->Expansion += includedFile;
|
||||||
MacroExpansionState->Expansion += '"';
|
MacroExpansionState->Expansion += '"';
|
||||||
@@ -2640,8 +2675,8 @@ public:
|
|||||||
|
|
||||||
IdentifierInfo *Ident = Tok.getIdentifierInfo();
|
IdentifierInfo *Ident = Tok.getIdentifierInfo();
|
||||||
if (Ident) {
|
if (Ident) {
|
||||||
std::string Mangled =
|
std::string Mangled = std::string("M_") +
|
||||||
std::string("M_") + mangleLocation(Loc, std::string(Ident->getName()));
|
mangleLocation(Loc, std::string(Ident->getName()));
|
||||||
visitIdentifier("def", "macro", Ident->getName(), Loc, Mangled);
|
visitIdentifier("def", "macro", Ident->getName(), Loc, Mangled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2661,13 +2696,14 @@ public:
|
|||||||
IdentifierInfo *Ident = Tok.getIdentifierInfo();
|
IdentifierInfo *Ident = Tok.getIdentifierInfo();
|
||||||
if (Ident) {
|
if (Ident) {
|
||||||
std::string Mangled =
|
std::string Mangled =
|
||||||
std::string("M_") +
|
std::string("M_") + mangleLocation(Macro->getDefinitionLoc(),
|
||||||
mangleLocation(Macro->getDefinitionLoc(), std::string(Ident->getName()));
|
std::string(Ident->getName()));
|
||||||
visitIdentifier("use", "macro", Ident->getName(), Loc, Mangled);
|
visitIdentifier("use", "macro", Ident->getName(), Loc, Mangled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void beginMacroExpansion(const Token &Tok, const MacroInfo *Macro, SourceRange Range) {
|
void beginMacroExpansion(const Token &Tok, const MacroInfo *Macro,
|
||||||
|
SourceRange Range) {
|
||||||
if (!Macro)
|
if (!Macro)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -2683,12 +2719,19 @@ public:
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (MacroExpansionState) {
|
if (MacroExpansionState) {
|
||||||
const auto InMacroArgs = MacroExpansionState->Range.fullyContains(SM.getExpansionRange(Range).getAsRange());
|
const auto InMacroArgs = MacroExpansionState->Range.fullyContains(
|
||||||
const auto InMacroBody = SM.getExpansionLoc(Tok.getLocation()) == SM.getExpansionLoc(MacroExpansionState->MacroNameToken.getLocation());
|
SM.getExpansionRange(Range).getAsRange());
|
||||||
|
const auto InMacroBody =
|
||||||
|
SM.getExpansionLoc(Tok.getLocation()) ==
|
||||||
|
SM.getExpansionLoc(MacroExpansionState->MacroNameToken.getLocation());
|
||||||
if (InMacroArgs || InMacroBody) {
|
if (InMacroArgs || InMacroBody) {
|
||||||
if (MacroExpansionState->MacroInfo->getDefinitionLoc() != Macro->getDefinitionLoc()) {
|
if (MacroExpansionState->MacroInfo->getDefinitionLoc() !=
|
||||||
|
Macro->getDefinitionLoc()) {
|
||||||
IdentifierInfo *DependencyIdent = Tok.getIdentifierInfo();
|
IdentifierInfo *DependencyIdent = Tok.getIdentifierInfo();
|
||||||
std::string DependencySymbol = std::string("M_") + mangleLocation(Macro->getDefinitionLoc(), std::string(DependencyIdent->getName()));
|
std::string DependencySymbol =
|
||||||
|
std::string("M_") +
|
||||||
|
mangleLocation(Macro->getDefinitionLoc(),
|
||||||
|
std::string(DependencyIdent->getName()));
|
||||||
|
|
||||||
MacroExpansionState->Dependencies.push_back(DependencySymbol);
|
MacroExpansionState->Dependencies.push_back(DependencySymbol);
|
||||||
}
|
}
|
||||||
@@ -2712,31 +2755,38 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void endMacroExpansion() {
|
void endMacroExpansion() {
|
||||||
// large macros are too slow to reformat, don't reformat macros larger than those arbitrary thresholds
|
// large macros are too slow to reformat, don't reformat macros larger than
|
||||||
|
// those arbitrary thresholds
|
||||||
static constexpr auto includedFileExpansionReformatThreshold = 20'000;
|
static constexpr auto includedFileExpansionReformatThreshold = 20'000;
|
||||||
static constexpr auto mainFileExpansionReformatThreshold = 200'000;
|
static constexpr auto mainFileExpansionReformatThreshold = 200'000;
|
||||||
|
|
||||||
const auto expansionLocation = SM.getExpansionLoc(MacroExpansionState->MacroNameToken.getLocation());
|
const auto expansionLocation =
|
||||||
|
SM.getExpansionLoc(MacroExpansionState->MacroNameToken.getLocation());
|
||||||
const auto expansionFilename = SM.getFilename(expansionLocation);
|
const auto expansionFilename = SM.getFilename(expansionLocation);
|
||||||
const auto includedExtensions = std::array{".h", ".hpp", ".hxx", ".inc", ".def"};
|
const auto includedExtensions =
|
||||||
const auto isIncludedFile = std::any_of(includedExtensions.begin(), includedExtensions.end(), [&](const auto *extension) {
|
std::array{".h", ".hpp", ".hxx", ".inc", ".def"};
|
||||||
|
const auto isIncludedFile =
|
||||||
|
std::any_of(includedExtensions.begin(), includedExtensions.end(),
|
||||||
|
[&](const auto *extension) {
|
||||||
return expansionFilename.ends_with_insensitive(extension);
|
return expansionFilename.ends_with_insensitive(extension);
|
||||||
});
|
});
|
||||||
const auto expansionReformatThreshold = isIncludedFile ? includedFileExpansionReformatThreshold : mainFileExpansionReformatThreshold;
|
const auto expansionReformatThreshold =
|
||||||
|
isIncludedFile ? includedFileExpansionReformatThreshold
|
||||||
|
: mainFileExpansionReformatThreshold;
|
||||||
|
|
||||||
if (MacroExpansionState->Expansion.length() < expansionReformatThreshold) {
|
if (MacroExpansionState->Expansion.length() < expansionReformatThreshold) {
|
||||||
// large macros are too memory-hungry to reformat with ColumnLimit != 0
|
// large macros are too memory-hungry to reformat with ColumnLimit != 0
|
||||||
// see https://github.com/llvm/llvm-project/issues/107434
|
// see https://github.com/llvm/llvm-project/issues/107434
|
||||||
auto style = clang::format::getMozillaStyle();
|
auto style = clang::format::getMozillaStyle();
|
||||||
if (MacroExpansionState->Expansion.length() > includedFileExpansionReformatThreshold)
|
if (MacroExpansionState->Expansion.length() >
|
||||||
|
includedFileExpansionReformatThreshold)
|
||||||
style.ColumnLimit = 0;
|
style.ColumnLimit = 0;
|
||||||
|
|
||||||
const auto replacements = clang::format::reformat(
|
const auto replacements = clang::format::reformat(
|
||||||
style,
|
style, MacroExpansionState->Expansion,
|
||||||
MacroExpansionState->Expansion,
|
{tooling::Range(0, MacroExpansionState->Expansion.length())});
|
||||||
{tooling::Range(0, MacroExpansionState->Expansion.length())}
|
auto formatted = clang::tooling::applyAllReplacements(
|
||||||
);
|
MacroExpansionState->Expansion, replacements);
|
||||||
auto formatted = clang::tooling::applyAllReplacements(MacroExpansionState->Expansion, replacements);
|
|
||||||
if (formatted) {
|
if (formatted) {
|
||||||
for (auto &[k, v] : MacroExpansionState->TokenLocations) {
|
for (auto &[k, v] : MacroExpansionState->TokenLocations) {
|
||||||
v = replacements.getShiftedCodePosition(v);
|
v = replacements.getShiftedCodePosition(v);
|
||||||
@@ -2745,15 +2795,18 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentifierInfo *Ident = MacroExpansionState->MacroNameToken.getIdentifierInfo();
|
IdentifierInfo *Ident =
|
||||||
|
MacroExpansionState->MacroNameToken.getIdentifierInfo();
|
||||||
std::string Symbol =
|
std::string Symbol =
|
||||||
std::string("M_") +
|
std::string("M_") +
|
||||||
mangleLocation(MacroExpansionState->MacroInfo->getDefinitionLoc(), std::string(Ident->getName()));
|
mangleLocation(MacroExpansionState->MacroInfo->getDefinitionLoc(),
|
||||||
|
std::string(Ident->getName()));
|
||||||
|
|
||||||
const auto dependenciesBegin = MacroExpansionState->Dependencies.begin();
|
const auto dependenciesBegin = MacroExpansionState->Dependencies.begin();
|
||||||
const auto dependenciesEnd = MacroExpansionState->Dependencies.end();
|
const auto dependenciesEnd = MacroExpansionState->Dependencies.end();
|
||||||
std::sort(dependenciesBegin, dependenciesEnd);
|
std::sort(dependenciesBegin, dependenciesEnd);
|
||||||
MacroExpansionState->Dependencies.erase(std::unique(dependenciesBegin, dependenciesEnd), dependenciesEnd);
|
MacroExpansionState->Dependencies.erase(
|
||||||
|
std::unique(dependenciesBegin, dependenciesEnd), dependenciesEnd);
|
||||||
|
|
||||||
auto Key = Symbol;
|
auto Key = Symbol;
|
||||||
for (const auto &Dependency : MacroExpansionState->Dependencies) {
|
for (const auto &Dependency : MacroExpansionState->Dependencies) {
|
||||||
@@ -2773,7 +2826,8 @@ public:
|
|||||||
|
|
||||||
MacroExpansionState.reset();
|
MacroExpansionState.reset();
|
||||||
|
|
||||||
macroUsed(MacroExpansionState->MacroNameToken, MacroExpansionState->MacroInfo);
|
macroUsed(MacroExpansionState->MacroNameToken,
|
||||||
|
MacroExpansionState->MacroInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onTokenLexed(const Token &Tok) {
|
void onTokenLexed(const Token &Tok) {
|
||||||
@@ -2787,7 +2841,8 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConcatInfo.AvoidConcat(MacroExpansionState->PrevPrevTok, MacroExpansionState->PrevTok, Tok)) {
|
if (ConcatInfo.AvoidConcat(MacroExpansionState->PrevPrevTok,
|
||||||
|
MacroExpansionState->PrevTok, Tok)) {
|
||||||
MacroExpansionState->Expansion += ' ';
|
MacroExpansionState->Expansion += ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2799,7 +2854,8 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
const auto spelling = CI.getPreprocessor().getSpelling(Tok);
|
const auto spelling = CI.getPreprocessor().getSpelling(Tok);
|
||||||
if (Tok.isAnyIdentifier()) {
|
if (Tok.isAnyIdentifier()) {
|
||||||
MacroExpansionState->TokenLocations[SLoc] = MacroExpansionState->Expansion.length();
|
MacroExpansionState->TokenLocations[SLoc] =
|
||||||
|
MacroExpansionState->Expansion.length();
|
||||||
}
|
}
|
||||||
MacroExpansionState->Expansion += spelling;
|
MacroExpansionState->Expansion += spelling;
|
||||||
}
|
}
|
||||||
@@ -2826,11 +2882,9 @@ void PreprocessorHook::FileChanged(SourceLocation Loc, FileChangeReason Reason,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreprocessorHook::InclusionDirective(SourceLocation HashLoc,
|
void PreprocessorHook::InclusionDirective(
|
||||||
const Token &IncludeTok,
|
SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
|
||||||
StringRef FileName,
|
bool IsAngled, CharSourceRange FileNameRange,
|
||||||
bool IsAngled,
|
|
||||||
CharSourceRange FileNameRange,
|
|
||||||
#if CLANG_VERSION_MAJOR >= 16
|
#if CLANG_VERSION_MAJOR >= 16
|
||||||
OptionalFileEntryRef File,
|
OptionalFileEntryRef File,
|
||||||
#elif CLANG_VERSION_MAJOR >= 15
|
#elif CLANG_VERSION_MAJOR >= 15
|
||||||
@@ -2838,11 +2892,9 @@ void PreprocessorHook::InclusionDirective(SourceLocation HashLoc,
|
|||||||
#else
|
#else
|
||||||
const FileEntry *File,
|
const FileEntry *File,
|
||||||
#endif
|
#endif
|
||||||
StringRef SearchPath,
|
StringRef SearchPath, StringRef RelativePath,
|
||||||
StringRef RelativePath,
|
|
||||||
#if CLANG_VERSION_MAJOR >= 19
|
#if CLANG_VERSION_MAJOR >= 19
|
||||||
const Module *SuggestedModule,
|
const Module *SuggestedModule, bool ModuleImported,
|
||||||
bool ModuleImported,
|
|
||||||
#else
|
#else
|
||||||
const Module *Imported,
|
const Module *Imported,
|
||||||
#endif
|
#endif
|
||||||
@@ -2851,7 +2903,8 @@ void PreprocessorHook::InclusionDirective(SourceLocation HashLoc,
|
|||||||
if (!File) {
|
if (!File) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Indexer->inclusionDirective(FileNameRange.getAsRange(), &File->getFileEntry());
|
Indexer->inclusionDirective(FileNameRange.getAsRange(),
|
||||||
|
&File->getFileEntry());
|
||||||
#else
|
#else
|
||||||
Indexer->inclusionDirective(FileNameRange.getAsRange(), File);
|
Indexer->inclusionDirective(FileNameRange.getAsRange(), File);
|
||||||
#endif
|
#endif
|
||||||
@@ -2869,8 +2922,7 @@ void PreprocessorHook::MacroExpands(const Token &Tok, const MacroDefinition &Md,
|
|||||||
|
|
||||||
void PreprocessorHook::MacroUndefined(const Token &Tok,
|
void PreprocessorHook::MacroUndefined(const Token &Tok,
|
||||||
const MacroDefinition &Md,
|
const MacroDefinition &Md,
|
||||||
const MacroDirective *Undef)
|
const MacroDirective *Undef) {
|
||||||
{
|
|
||||||
Indexer->macroUsed(Tok, Md.getMacroInfo());
|
Indexer->macroUsed(Tok, Md.getMacroInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,4 @@ std::string hash(const std::string &Str) {
|
|||||||
return std::string(HashStr);
|
return std::string(HashStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string toString(int N) {
|
std::string toString(int N) { return stringFormat("%d", N); }
|
||||||
return stringFormat("%d", N);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
#define StringOperations_h
|
#define StringOperations_h
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
std::string hash(const std::string &Str);
|
std::string hash(const std::string &Str);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user