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:
Nicolas Guichard
2024-11-28 00:04:18 +00:00
parent 6126601e77
commit 08d24b12c7
6 changed files with 505 additions and 443 deletions

View File

@@ -31,12 +31,13 @@ using namespace clang;
namespace {
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;
InputIt currentName;
for (currentName = first; currentName != last; currentName++) {
if (!currentDecl || !currentDecl->getIdentifier() || currentDecl->getName() != *currentName)
if (!currentDecl || !currentDecl->getIdentifier() ||
currentDecl->getName() != *currentName)
return false;
currentDecl = dyn_cast<NamedDecl>(currentDecl->getDeclContext());
@@ -50,20 +51,21 @@ bool hasReverseQualifiedName(InputIt first, InputIt last, const NamedDecl &tag)
return true;
}
bool isMozillaJniObjectBase(const CXXRecordDecl &klass)
{
const auto qualifiedName = std::array<StringRef, 3>{"mozilla", "jni", "ObjectBase"};
return hasReverseQualifiedName(qualifiedName.crbegin(), qualifiedName.crend(), klass);
bool isMozillaJniObjectBase(const CXXRecordDecl &klass) {
const auto qualifiedName =
std::array<StringRef, 3>{"mozilla", "jni", "ObjectBase"};
return hasReverseQualifiedName(qualifiedName.crbegin(), qualifiedName.crend(),
klass);
}
bool isMozillaJniNativeImpl(const CXXRecordDecl &klass)
{
const auto qualifiedName = std::array<StringRef, 3>{"mozilla", "jni", "NativeImpl"};
return hasReverseQualifiedName(qualifiedName.crbegin(), qualifiedName.crend(), klass);
bool isMozillaJniNativeImpl(const CXXRecordDecl &klass) {
const auto qualifiedName =
std::array<StringRef, 3>{"mozilla", "jni", "NativeImpl"};
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()) {
const auto *namedDecl = dyn_cast<VarDecl>(decl);
if (!namedDecl)
@@ -78,8 +80,7 @@ const NamedDecl *fieldNamed(StringRef name, const RecordDecl &strukt)
return {};
}
optional<StringRef> nameFieldValue(const RecordDecl &strukt)
{
optional<StringRef> nameFieldValue(const RecordDecl &strukt) {
const auto *nameField = dyn_cast_or_null<VarDecl>(fieldNamed("name", strukt));
if (!nameField)
return {};
@@ -107,18 +108,14 @@ struct AbstractBinding {
"jvm",
};
static optional<Lang> langFromString(StringRef langName)
{
static optional<Lang> langFromString(StringRef langName) {
const auto it = std::find(langNames.begin(), langNames.end(), langName);
if (it == langNames.end())
return {};
return Lang(it - langNames.begin());
}
static StringRef stringFromLang(Lang lang)
{
return langNames[size_t(lang)];
}
static StringRef stringFromLang(Lang lang) { return langNames[size_t(lang)]; }
// Subset of tools/analysis/BindingSlotKind
enum class Kind {
@@ -130,34 +127,28 @@ struct AbstractBinding {
};
static constexpr size_t KindLength = 5;
static constexpr std::array<StringRef, KindLength> kindNames = {
"class",
"method",
"getter",
"setter",
"const",
"class", "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);
if (it == kindNames.end())
return {};
return Kind(it - kindNames.begin());
}
static StringRef stringFromKind(Kind kind)
{
return kindNames[size_t(kind)];
}
static StringRef stringFromKind(Kind kind) { return kindNames[size_t(kind)]; }
Lang lang;
Kind kind;
StringRef symbol;
};
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 std::array<StringRef, AbstractBinding::LangLength> AbstractBinding::langNames;
constexpr std::array<StringRef, AbstractBinding::LangLength>
AbstractBinding::langNames;
struct BindingTo : public AbstractBinding {
BindingTo(AbstractBinding b) : AbstractBinding(std::move(b)) {}
@@ -172,24 +163,25 @@ struct BoundAs : public AbstractBinding {
constexpr StringRef BoundAs::ANNOTATION;
template <typename B>
void setBindingAttr(ASTContext &C, Decl &decl, B binding)
{
void setBindingAttr(ASTContext &C, Decl &decl, B binding) {
#if CLANG_VERSION_MAJOR >= 18
auto utf8 = StringLiteralKind::UTF8;
#else
auto utf8 = StringLiteral::UTF8;
#endif
// recent LLVM: CreateImplicit then setDelayedArgs
Expr *langExpr = StringLiteral::Create(C, AbstractBinding::stringFromLang(binding.lang), utf8, false, {}, {});
Expr *kindExpr = StringLiteral::Create(C, AbstractBinding::stringFromKind(binding.kind), utf8, false, {}, {});
Expr *symbolExpr = StringLiteral::Create(C, binding.symbol, utf8, false, {}, {});
Expr *langExpr = StringLiteral::Create(
C, AbstractBinding::stringFromLang(binding.lang), 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 *attr = AnnotateAttr::CreateImplicit(C, B::ANNOTATION, args, 3);
decl.addAttr(attr);
}
optional<AbstractBinding> readBinding(const AnnotateAttr &attr)
{
optional<AbstractBinding> readBinding(const AnnotateAttr &attr) {
if (attr.args_size() != 3)
return {};
@@ -199,9 +191,12 @@ optional<AbstractBinding> readBinding(const AnnotateAttr &attr)
if (!langExpr || !kindExpr || !symbolExpr)
return {};
const auto *langName = dyn_cast<StringLiteral>(langExpr->IgnoreUnlessSpelledInSource());
const auto *kindName = dyn_cast<StringLiteral>(kindExpr->IgnoreUnlessSpelledInSource());
const auto *symbol = dyn_cast<StringLiteral>(symbolExpr->IgnoreUnlessSpelledInSource());
const auto *langName =
dyn_cast<StringLiteral>(langExpr->IgnoreUnlessSpelledInSource());
const auto *kindName =
dyn_cast<StringLiteral>(kindExpr->IgnoreUnlessSpelledInSource());
const auto *symbol =
dyn_cast<StringLiteral>(symbolExpr->IgnoreUnlessSpelledInSource());
if (!langName || !kindName || !symbol)
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>()) {
if (attr->getAnnotation() != BindingTo::ANNOTATION)
continue;
@@ -234,8 +228,7 @@ optional<BindingTo> getBindingTo(const Decl &decl)
}
// C++23: turn into generator
std::vector<BoundAs> getBoundAs(const Decl &decl)
{
std::vector<BoundAs> getBoundAs(const Decl &decl) {
std::vector<BoundAs> found;
for (const auto *attr : decl.specific_attrs<AnnotateAttr>()) {
@@ -252,8 +245,7 @@ std::vector<BoundAs> getBoundAs(const Decl &decl)
return found;
}
class FindCallCall : private RecursiveASTVisitor<FindCallCall>
{
class FindCallCall : private RecursiveASTVisitor<FindCallCall> {
public:
struct Result {
using Kind = AbstractBinding::Kind;
@@ -262,8 +254,7 @@ public:
StringRef name;
};
static optional<Result> search(Stmt *statement)
{
static optional<Result> search(Stmt *statement) {
FindCallCall finder;
finder.TraverseStmt(statement);
return finder.result;
@@ -275,7 +266,8 @@ private:
friend RecursiveASTVisitor<FindCallCall>;
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)
return {};
@@ -287,7 +279,8 @@ private:
if (action != "Call" && action != "Get" && action != "Set")
return {};
const auto *parentClass = dyn_cast_or_null<ClassTemplateSpecializationDecl>(callee->getParent());
const auto *parentClass =
dyn_cast_or_null<ClassTemplateSpecializationDecl>(callee->getParent());
if (!parentClass)
return {};
@@ -318,7 +311,8 @@ private:
return {};
}
const auto *templateArg = parentClass->getTemplateArgs().get(0).getAsType()->getAsRecordDecl();
const auto *templateArg =
parentClass->getTemplateArgs().get(0).getAsType()->getAsRecordDecl();
if (!templateArg)
return {};
@@ -334,16 +328,15 @@ private:
return {};
}
bool VisitCallExpr(CallExpr *callExpr)
{
bool VisitCallExpr(CallExpr *callExpr) {
return !(result = tryParseCallCall(callExpr));
}
};
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();
switch (kind) {
@@ -364,8 +357,7 @@ std::string javaScipSymbol(StringRef prefix, StringRef name, AbstractBinding::Ki
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)) {
J.attributeBegin("slotOwner");
J.objectBegin();
@@ -377,8 +369,7 @@ void addSlotOwnerAttribute(llvm::json::OStream &J, const Decl &decl)
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);
if (!allBoundAs.empty()) {
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:
// - _0xxxx is the utf16 code unit xxxx
// - _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 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
// 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.
optional<std::string> demangleJnicallPart(StringRef &remainder)
{
// But we don't use the later for now because we have no way to map that to how
// SCIP resolves overloads.
optional<std::string> demangleJnicallPart(StringRef &remainder) {
std::string demangled;
std::mbstate_t ps = {};
@@ -467,7 +460,8 @@ optional<std::string> demangleJnicallPart(StringRef &remainder)
default:
// either:
// * 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;
}
default:
@@ -483,8 +477,8 @@ optional<std::string> demangleJnicallPart(StringRef &remainder)
return demangled;
}
optional<std::string> scipSymbolFromJnicallFunctionName(StringRef functionName)
{
optional<std::string>
scipSymbolFromJnicallFunctionName(StringRef functionName) {
if (!functionName.consume_front("Java_"))
return {};
@@ -493,7 +487,8 @@ optional<std::string> scipSymbolFromJnicallFunctionName(StringRef functionName)
if (!demangledName || demangledName->empty())
return {};
// demangleJavaName returns something like .some.package.Class$InnerClass.method
// demangleJavaName returns something like
// .some.package.Class$InnerClass.method
// - prepend S_jvm_
// - remove the leading dot
// - 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(), '$', '#');
// Keep track of how many times we have seen this method, to build the ([+overloadNumber]). suffix.
// This assumes this function is called on C function definitions in the same order the matching overloads are declared in Java.
// Keep track of how many times we have seen this method, to build the
// ([+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;
auto &overloadNumber = jnicallFunctions[symbol];
@@ -530,8 +527,7 @@ optional<std::string> scipSymbolFromJnicallFunctionName(StringRef functionName)
// {
// static constexpr char name[] = "[nameFieldValue]";
// }
void findBindingToJavaClass(ASTContext &C, CXXRecordDecl &klass)
{
void findBindingToJavaClass(ASTContext &C, CXXRecordDecl &klass) {
for (const auto &baseSpecifier : klass.bases()) {
const auto *base = baseSpecifier.getType()->getAsCXXRecordDecl();
if (!base)
@@ -544,7 +540,8 @@ void findBindingToJavaClass(ASTContext &C, CXXRecordDecl &klass)
if (!name)
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{{
.lang = BindingTo::Lang::Jvm,
.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
// named Java_<mangled method name>[__<mangled overload specification>].
void findBindingToJavaFunction(ASTContext &C, FunctionDecl &function)
{
// When a Java method is marked as native, the JRE looks by default for a
// function named Java_<mangled method name>[__<mangled overload
// specification>].
void findBindingToJavaFunction(ASTContext &C, FunctionDecl &function) {
const auto *identifier = function.getIdentifier();
if (!identifier)
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();
if (!parent)
return;
@@ -607,7 +603,8 @@ void findBindingToJavaMember(ASTContext &C, CXXMethodDecl &method)
if (!found)
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{{
.lang = BindingTo::Lang::Jvm,
.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());
if (!parent)
return;
@@ -639,7 +635,8 @@ void findBindingToJavaConstant(ASTContext &C, VarDecl &field)
if (!classBinding)
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{{
.lang = BindingTo::Lang::Jvm,
.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()) {
const auto *base = baseSpecifier.getType()->getAsCXXRecordDecl();
if (!base)
continue;
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)
continue;
if (!isMozillaJniNativeImpl(*baseBase))
continue;
const auto *wrapper = baseBase->getTemplateArgs().get(0).getAsType()->getAsCXXRecordDecl();
const auto *wrapper =
baseBase->getTemplateArgs().get(0).getAsType()->getAsCXXRecordDecl();
if (!wrapper)
continue;
@@ -691,7 +689,8 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
if (!name)
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{{
.lang = BoundAs::Lang::Jvm,
.kind = BoundAs::Kind::Class,
@@ -699,7 +698,8 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
}};
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)
continue;
@@ -714,7 +714,8 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
std::set<const CXXMethodDecl *> alreadyBound;
for (const auto *init : inits->inits()) {
const auto *call = dyn_cast<CallExpr>(init->IgnoreUnlessSpelledInSource());
const auto *call =
dyn_cast<CallExpr>(init->IgnoreUnlessSpelledInSource());
if (!call)
continue;
@@ -726,15 +727,18 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
if (!templateArgs)
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)
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)
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)
continue;
@@ -760,17 +764,22 @@ void findBoundAsJavaClasses(ASTContext &C, CXXRecordDecl &klass)
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());
if (!method)
continue;
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
// In case of overloads it's not obvious which one we should use
// this expects the declaration order between C++ and Java to match
auto declarations = std::vector<Decl*>(bound->decls_begin(), bound->decls_end());
auto byLocation = [](Decl *a, Decl *b){ return a->getLocation() < b->getLocation(); };
auto declarations =
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);
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);
addBindingSlotsAttribute(J, decl);
}

View File

@@ -10,8 +10,10 @@
void findBindingToJavaClass(clang::ASTContext &C, clang::CXXRecordDecl &klass);
void findBoundAsJavaClasses(clang::ASTContext &C, clang::CXXRecordDecl &klass);
void findBindingToJavaFunction(clang::ASTContext &C, clang::FunctionDecl &function);
void findBindingToJavaMember(clang::ASTContext &C, clang::CXXMethodDecl &method);
void findBindingToJavaFunction(clang::ASTContext &C,
clang::FunctionDecl &function);
void findBindingToJavaMember(clang::ASTContext &C,
clang::CXXMethodDecl &method);
void findBindingToJavaConstant(clang::ASTContext &C, clang::VarDecl &field);
void emitBindingAttributes(llvm::json::OStream &json, const clang::Decl &decl);

View File

@@ -9,10 +9,10 @@
#include <stdlib.h>
#if defined(_WIN32) || defined(_WIN64)
#include "StringOperations.h"
#include <direct.h>
#include <io.h>
#include <windows.h>
#include "StringOperations.h"
#else
#include <sys/file.h>
#include <sys/time.h>
@@ -50,7 +50,8 @@ void ensurePath(std::string Path) {
}
#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;
std::string Hash = hash(SrcFile);
std::string MutexName = std::string("Local\\searchfox-") + Hash;
@@ -71,12 +72,11 @@ AutoLockFile::~AutoLockFile() {
CloseHandle(Handle);
}
bool AutoLockFile::success() {
return Handle != NULL;
}
bool AutoLockFile::success() { return Handle != NULL; }
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");
}
@@ -97,7 +97,8 @@ std::string getAbsolutePath(const std::string &Filename) {
return std::string(Full);
}
#else
AutoLockFile::AutoLockFile(const std::string &SrcFile, const std::string &DstFile) {
AutoLockFile::AutoLockFile(const std::string &SrcFile,
const std::string &DstFile) {
this->Filename = DstFile;
FileDescriptor = open(SrcFile.c_str(), O_RDONLY);
if (FileDescriptor == -1) {
@@ -117,7 +118,8 @@ AutoLockFile::~AutoLockFile() { close(FileDescriptor); }
bool AutoLockFile::success() { return FileDescriptor != -1; }
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");
}

View File

@@ -96,7 +96,8 @@ FileType relativizePath(std::string& path) {
// Empty filenames can get turned into Srcdir when they are resolved as
// absolute paths, so we should exclude files that are exactly equal to
// 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.
path.erase(0, Srcdir.length() + 1);
return FileType::Source;
@@ -142,13 +143,9 @@ static bool isASCII(const std::string& Input) {
}
struct RAIITracer {
RAIITracer(const char *log) : mLog(log) {
printf("<%s>\n", mLog);
}
RAIITracer(const char *log) : mLog(log) { printf("<%s>\n", mLog); }
~RAIITracer() {
printf("</%s>\n", mLog);
}
~RAIITracer() { printf("</%s>\n", mLog); }
const char *mLog;
};
@@ -157,21 +154,16 @@ struct RAIITracer {
// Sets variable to value on creation then resets variable to its original
// value on destruction
template<typename T>
class ValueRollback {
template <typename T> class ValueRollback {
public:
template <typename U = T>
ValueRollback(T &variable, U &&value)
: mVariable{&variable}
, mSavedValue{std::exchange(variable, std::forward<U>(value))}
{
}
: mVariable{&variable},
mSavedValue{std::exchange(variable, std::forward<U>(value))} {}
ValueRollback(ValueRollback &&other) noexcept
: mVariable{std::exchange(other.mVariable, nullptr)}
, mSavedValue{std::move(other.mSavedValue)}
{
}
: mVariable{std::exchange(other.mVariable, nullptr)},
mSavedValue{std::move(other.mSavedValue)} {}
ValueRollback(const ValueRollback &) = delete;
ValueRollback &operator=(ValueRollback &&) = delete;
@@ -227,7 +219,8 @@ struct FileInfo {
struct MacroExpansionState {
Token MacroNameToken;
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::map<SourceLocation, unsigned> TokenLocations;
SourceRange Range;
@@ -255,10 +248,8 @@ public:
FileID PrevFID) override;
virtual void InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
StringRef FileName,
bool IsAngled,
CharSourceRange FileNameRange,
const Token &IncludeTok, StringRef FileName,
bool IsAngled, CharSourceRange FileNameRange,
#if CLANG_VERSION_MAJOR >= 16
OptionalFileEntryRef File,
#elif CLANG_VERSION_MAJOR >= 15
@@ -266,8 +257,7 @@ public:
#else
const FileEntry *File,
#endif
StringRef SearchPath,
StringRef RelativePath,
StringRef SearchPath, StringRef RelativePath,
#if CLANG_VERSION_MAJOR >= 19
const Module *SuggestedModule,
bool ModuleImported,
@@ -314,9 +304,11 @@ private:
// Tracks the set of declarations that the current expression/statement is
// nested inside of.
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) {
this->VisitImplicit = VisitImplicit || (Prev ? Prev->VisitImplicit : false);
this->VisitImplicit =
VisitImplicit || (Prev ? Prev->VisitImplicit : false);
Self->CurDeclContext = this;
}
@@ -453,7 +445,8 @@ private:
if (IsInvalid) {
return "";
}
unsigned Column1 = SM.getColumnNumber(Begin.first, Begin.second, &IsInvalid);
unsigned Column1 =
SM.getColumnNumber(Begin.first, Begin.second, &IsInvalid);
if (IsInvalid) {
return "";
}
@@ -496,8 +489,8 @@ private:
std::string Backing;
llvm::raw_string_ostream Stream(Backing);
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
printTemplateArgumentList(
Stream, TemplateArgs.asArray(), PrintingPolicy(CI.getLangOpts()));
printTemplateArgumentList(Stream, TemplateArgs.asArray(),
PrintingPolicy(CI.getLangOpts()));
Result += Stream.str();
}
} 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
// different platforms map to the same thing.
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));
}
@@ -569,8 +563,8 @@ private:
// The majority of path characters are letters and slashes which don't get
// encoded, so that satisfies (1). Since "@" characters in the unsanitized
// path get encoded, there should be no "@" characters in the sanitized path
// that got preserved from the unsanitized input, so that should satisfy (2).
// And (3) was done by trial-and-error. Note in particular the dot (.)
// that got preserved from the unsanitized input, so that should satisfy
// (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
// doesn't work correctly, as all dot characters in the symbol query get
// replaced by #.
@@ -591,7 +585,8 @@ private:
// we can end up with hash collisions where different symbols from
// different platforms map to the same thing.
char *Platform = getenv("MOZSEARCH_PLATFORM");
Filename = std::string(Platform ? Platform : "") + std::string("@") + Filename;
Filename =
std::string(Platform ? Platform : "") + std::string("@") + Filename;
}
return Filename;
}
@@ -708,11 +703,11 @@ private:
public:
IndexConsumer(CompilerInstance &CI)
: CI(CI), SM(CI.getSourceManager()), LO(CI.getLangOpts()), CurMangleContext(nullptr),
AstContext(nullptr), ConcatInfo(CI.getPreprocessor()), CurDeclContext(nullptr),
: CI(CI), SM(CI.getSourceManager()), LO(CI.getLangOpts()),
CurMangleContext(nullptr), AstContext(nullptr),
ConcatInfo(CI.getPreprocessor()), CurDeclContext(nullptr),
TemplateStack(nullptr) {
CI.getPreprocessor().addPPCallbacks(
make_unique<PreprocessorHook>(this));
CI.getPreprocessor().addPPCallbacks(make_unique<PreprocessorHook>(this));
CI.getPreprocessor().setTokenWatcher(
[this](const auto &token) { onTokenLexed(token); });
}
@@ -757,8 +752,8 @@ public:
FileInfo &Info = *It->second;
std::string Filename = Outdir + Info.Realname;
std::string SrcFilename = Info.Generated
? Objdir + Info.Realname.substr(GENERATED.length())
std::string SrcFilename =
Info.Generated ? Objdir + Info.Realname.substr(GENERATED.length())
: Srcdir + PATHSEP_STRING + Info.Realname;
ensurePath(Filename);
@@ -778,13 +773,15 @@ public:
std::ifstream Fin(Filename.c_str(), std::ios::in | std::ios::binary);
FILE *OutFp = Lock.openTmp();
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);
}
// Sort our new results and get an iterator to them
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;
// Loop over the existing (sorted) lines in the analysis output file.
@@ -815,8 +812,10 @@ public:
// dedupe the new entries being written
continue;
}
if (fwrite(NewLinesIter->c_str(), NewLinesIter->length(), 1, OutFp) != 1) {
fprintf(stderr, "Unable to write %zu bytes[1] to tmp output file for %s\n",
if (fwrite(NewLinesIter->c_str(), NewLinesIter->length(), 1, OutFp) !=
1) {
fprintf(stderr,
"Unable to write %zu bytes[1] to tmp output file for %s\n",
NewLinesIter->length(), Filename.c_str());
exit(1);
}
@@ -825,7 +824,8 @@ public:
// Write the entry read from the existing file.
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());
exit(1);
}
@@ -839,8 +839,10 @@ public:
if (*NewLinesIter == LastNewWritten) {
continue;
}
if (fwrite(NewLinesIter->c_str(), NewLinesIter->length(), 1, OutFp) != 1) {
fprintf(stderr, "Unable to write %zu bytes[3] to tmp output file for %s\n",
if (fwrite(NewLinesIter->c_str(), NewLinesIter->length(), 1, OutFp) !=
1) {
fprintf(stderr,
"Unable to write %zu bytes[3] to tmp output file for %s\n",
NewLinesIter->length(), Filename.c_str());
exit(1);
}
@@ -851,7 +853,9 @@ public:
// with the new one.
fclose(OutFp);
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);
}
}
@@ -950,7 +954,8 @@ public:
D = F->getTemplateInstantiationPattern();
}
return Context(D->getQualifiedNameAsString(), getMangledName(CurMangleContext, D));
return Context(D->getQualifiedNameAsString(),
getMangledName(CurMangleContext, D));
}
Context getContext(SourceLocation Loc) {
@@ -990,7 +995,8 @@ public:
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 auto *Ctxt = CurDeclContext;
while (Ctxt) {
@@ -1033,9 +1039,9 @@ public:
// indexer to visit EVERY identifier, which is way too much data.
struct AutoTemplateContext {
AutoTemplateContext(IndexConsumer *Self)
: Self(Self)
, CurMode(Self->TemplateStack ? Self->TemplateStack->CurMode : Mode::GatherDependent)
, Parent(Self->TemplateStack) {
: Self(Self), CurMode(Self->TemplateStack ? Self->TemplateStack->CurMode
: Mode::GatherDependent),
Parent(Self->TemplateStack) {
Self->TemplateStack = this;
}
@@ -1066,9 +1072,7 @@ public:
}
}
bool inGatherMode() {
return CurMode == Mode::GatherDependent;
}
bool inGatherMode() { return CurMode == Mode::GatherDependent; }
// Do we need to perform the extra AnalyzeDependent passes (one per
// instantiation)?
@@ -1119,7 +1123,8 @@ public:
AutoTemplateContext *TemplateStack;
std::unordered_multimap<const FunctionDecl *, const Stmt *> ForwardingTemplates;
std::unordered_multimap<const FunctionDecl *, const Stmt *>
ForwardingTemplates;
std::unordered_set<unsigned> ForwardedTemplateLocations;
bool shouldVisitTemplateInstantiations() const {
@@ -1196,7 +1201,8 @@ public:
// Flag to omit the identifier from being cross-referenced across files.
// This is usually desired for local variables.
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.
NotIdentifierToken = 1 << 1,
// This indicates that the end of the provided SourceRange is valid and
@@ -1206,8 +1212,10 @@ public:
LocRangeEndValid = 1 << 2
};
void emitStructuredRecordInfo(llvm::json::OStream &J, SourceLocation Loc, const RecordDecl *decl) {
J.attribute("kind", TypeWithKeyword::getTagTypeKindName(decl->getTagKind()));
void emitStructuredRecordInfo(llvm::json::OStream &J, SourceLocation Loc,
const RecordDecl *decl) {
J.attribute("kind",
TypeWithKeyword::getTagTypeKindName(decl->getTagKind()));
const ASTContext &C = *AstContext;
const ASTRecordLayout &Layout = C.getASTRecordLayout(decl);
@@ -1226,7 +1234,8 @@ public:
// * the size string 4/8 is shorter than true/false in the analysis
// file
const QualType ptrType = C.getUIntPtrType();
J.attribute("ownVFPtrBytes", C.getTypeSizeInChars(ptrType).getQuantity());
J.attribute("ownVFPtrBytes",
C.getTypeSizeInChars(ptrType).getQuantity());
}
J.attributeBegin("supers");
@@ -1310,14 +1319,17 @@ public:
J.arrayBegin();
uint64_t iField = 0;
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;
auto sourceRange = SM.getExpansionRange(Field.getSourceRange()).getAsRange();
auto sourceRange =
SM.getExpansionRange(Field.getSourceRange()).getAsRange();
uint64_t localOffsetBits = Layout.getFieldOffset(iField);
CharUnits localOffsetBytes = C.toCharUnitsFromBits(localOffsetBits);
J.objectBegin();
J.attribute("lineRange", pathAndLineRangeToString(structFileID, sourceRange));
J.attribute("lineRange",
pathAndLineRangeToString(structFileID, sourceRange));
J.attribute("pretty", getQualifiedName(&Field));
J.attribute("sym", getMangledName(CurMangleContext, &Field));
@@ -1346,7 +1358,8 @@ public:
J.attributeBegin("bitPositions");
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.objectEnd();
@@ -1381,7 +1394,8 @@ public:
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);
J.attributeBegin("args");
@@ -1431,7 +1445,8 @@ public:
// TODO: Make sure we're doing template traversals appropriately...
// findOverriddenMethods (now removed) liked to do:
// 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
// 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.
*/
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");
@@ -1572,8 +1588,7 @@ public:
// called for each identifier that corresponds to a symbol.
void visitIdentifier(const char *Kind, const char *SyntaxKind,
llvm::StringRef QualName, SourceRange LocRange,
std::string Symbol,
QualType MaybeType = QualType(),
std::string Symbol, QualType MaybeType = QualType(),
Context TokenContext = Context(), int Flags = 0,
SourceRange PeekRange = SourceRange(),
SourceRange NestingRange = SourceRange(),
@@ -1583,7 +1598,9 @@ public:
// Also visit the spelling site.
SourceLocation SpellingLoc = SM.getSpellingLoc(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);
@@ -1598,12 +1615,16 @@ public:
// Find the file positions corresponding to the token.
unsigned StartOffset = SM.getFileOffset(ExpansionLoc);
unsigned EndOffset = (Flags & LocRangeEndValid)
unsigned EndOffset =
(Flags & LocRangeEndValid)
? 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 RangeStr = locationToString(ExpansionLoc, EndOffset - StartOffset);
std::string LocStr =
locationToString(ExpansionLoc, EndOffset - StartOffset);
std::string RangeStr =
locationToString(ExpansionLoc, EndOffset - StartOffset);
std::string PeekRangeStr;
if (!(Flags & NotIdentifierToken)) {
@@ -1745,7 +1766,8 @@ public:
J.objectBegin();
J.attributeBegin(macroInfo.Key);
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.attributeEnd();
J.objectEnd();
@@ -1757,7 +1779,8 @@ public:
J.objectBegin();
J.attributeBegin(macroInfo.Key);
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.value(it->second);
J.arrayEnd();
@@ -1815,7 +1838,8 @@ public:
// But if there are parameters, we want to include those as well.
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
// the parameters in that case.
@@ -1841,8 +1865,8 @@ public:
for (CXXBaseSpecifier &Base : D2->bases()) {
std::pair<FileID, unsigned> Loc = SM.getDecomposedLoc(Base.getEndLoc());
// It's possible there are macros involved or something. We don't include
// the parameters in that case.
// It's possible there are macros involved or something. We don't
// include the parameters in that case.
if (Loc.first == FuncLoc.first) {
// Assume parameters are in order, so we always take the last one.
End = Base.getEndLoc();
@@ -1854,8 +1878,7 @@ public:
}
SourceRange getCommentRange(NamedDecl *D) {
const RawComment* RC =
AstContext->getRawCommentForDeclNoCache(D);
const RawComment *RC = AstContext->getRawCommentForDeclNoCache(D);
if (!RC) {
return SourceRange();
}
@@ -1944,7 +1967,8 @@ public:
D = D2->getTemplateInstantiationPattern();
}
// We treat pure virtual declarations as definitions.
Kind = (D2->isThisDeclarationADefinition() || isPure(D2)) ? "def" : "decl";
Kind =
(D2->isThisDeclarationADefinition() || isPure(D2)) ? "def" : "decl";
PrettyKind = "function";
PeekRange = getFunctionPeekRange(D2);
@@ -1998,7 +2022,8 @@ public:
if (D2) {
// There's no exposure of the left brace so we have to find it.
NestingRange = SourceRange(
findLeftBraceFromLoc(D2->isAnonymousNamespace() ? D2->getBeginLoc() : ExpansionLoc),
findLeftBraceFromLoc(D2->isAnonymousNamespace() ? D2->getBeginLoc()
: ExpansionLoc),
D2->getRBraceLoc());
}
} else if (isa<FieldDecl>(D)) {
@@ -2024,9 +2049,9 @@ public:
// 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
// point to other places that generate destructors, such as a lambda (apparently
// clang 8 creates a destructor declaration for at least some lambdas). In
// that case we'll just drop the declaration.
// point to other places that generate destructors, such as a lambda
// (apparently clang 8 creates a destructor declaration for at least some
// lambdas). In that case we'll just drop the declaration.
if (isa<CXXDestructorDecl>(D)) {
PrettyKind = "destructor";
const char *P = SM.getCharacterData(Loc);
@@ -2046,9 +2071,9 @@ public:
}
}
visitIdentifier(Kind, PrettyKind, getQualifiedName(D), SourceRange(Loc), Symbol,
qtype,
getContext(D), Flags, PeekRange, NestingRange);
visitIdentifier(Kind, PrettyKind, getQualifiedName(D), SourceRange(Loc),
Symbol, qtype, getContext(D), Flags, PeekRange,
NestingRange);
// In-progress structured info emission.
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
// should be re-evaluated once this is working for normal classes and
// we can better evaluate what is useful.
!D2->isDependentType() &&
!TemplateStack) {
!D2->isDependentType() && !TemplateStack) {
if (auto *D3 = dyn_cast<CXXRecordDecl>(D2)) {
findBindingToJavaClass(*AstContext, *D3);
findBoundAsJavaClasses(*AstContext, *D3);
@@ -2082,10 +2106,8 @@ public:
if ((D2->isThisDeclarationADefinition() || isPure(D2)) &&
// a clause at the top should have generalized and set wasTemplate so
// it shouldn't be the case that isTemplateInstantiation() is true.
!D2->isTemplateInstantiation() &&
!wasTemplate &&
!D2->isFunctionTemplateSpecialization() &&
!TemplateStack) {
!D2->isTemplateInstantiation() && !wasTemplate &&
!D2->isFunctionTemplateSpecialization() && !TemplateStack) {
if (auto *D3 = dyn_cast<CXXMethodDecl>(D2)) {
findBindingToJavaMember(*AstContext, *D3);
} else {
@@ -2095,14 +2117,12 @@ public:
}
}
if (FieldDecl *D2 = dyn_cast<FieldDecl>(D)) {
if (!D2->isTemplated() &&
!TemplateStack) {
if (!D2->isTemplated() && !TemplateStack) {
emitStructuredInfo(ExpansionLoc, D2);
}
}
if (VarDecl *D2 = dyn_cast<VarDecl>(D)) {
if (!D2->isTemplated() &&
!TemplateStack &&
if (!D2->isTemplated() && !TemplateStack &&
isa<CXXRecordDecl>(D2->getDeclContext())) {
findBindingToJavaConstant(*AstContext, *D2);
emitStructuredInfo(ExpansionLoc, D2);
@@ -2118,11 +2138,14 @@ public:
return true;
}
// If we are in a template and find a Stmt that was registed in ForwardedTemplateLocations,
// convert the location to an actual Stmt* in ForwardingTemplates
// If we are in a template and find a Stmt that was registed in
// ForwardedTemplateLocations, convert the location to an actual Stmt* in
// ForwardingTemplates
if (TemplateStack && !TemplateStack->inGatherMode()) {
if (ForwardedTemplateLocations.find(E->getBeginLoc().getRawEncoding()) != ForwardedTemplateLocations.end()) {
ForwardingTemplates.insert({getCurrentFunctionTemplateInstantiation(), E});
if (ForwardedTemplateLocations.find(E->getBeginLoc().getRawEncoding()) !=
ForwardedTemplateLocations.end()) {
ForwardingTemplates.insert(
{getCurrentFunctionTemplateInstantiation(), E});
return true;
}
}
@@ -2148,8 +2171,9 @@ public:
}
bool VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
// If we are in a template and the callee is type-dependent, register it in ForwardedTemplateLocations
// to forward its uses to the surrounding template call site
// If we are in a template and the callee is type-dependent, register it in
// ForwardedTemplateLocations to forward its uses to the surrounding
// template call site
if (TemplateStack && TemplateStack->inGatherMode()) {
if (E->isTypeDependent()) {
TemplateStack->visitDependent(E->getBeginLoc());
@@ -2210,9 +2234,10 @@ public:
argRanges.push_back(argExpr->getSourceRange());
}
visitIdentifier("use", "function", getQualifiedName(NamedCallee), Loc, Mangled,
E->getCallReturnType(*AstContext), getContext(SpellingLoc), Flags,
SourceRange(), SourceRange(), &argRanges);
visitIdentifier("use", "function", getQualifiedName(NamedCallee), Loc,
Mangled, E->getCallReturnType(*AstContext),
getContext(SpellingLoc), Flags, SourceRange(),
SourceRange(), &argRanges);
return true;
}
@@ -2300,7 +2325,8 @@ public:
}
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 seen = std::unordered_set<const Stmt *>{};
while (!todo.empty()) {
@@ -2326,8 +2352,10 @@ public:
continue;
if (!F->isTemplateInstantiation())
continue;
const auto [ForwardedBegin, ForwardedEnd] = ForwardingTemplates.equal_range(F);
for (auto ForwardedIt = ForwardedBegin; ForwardedIt != ForwardedEnd; ++ForwardedIt)
const auto [ForwardedBegin, ForwardedEnd] =
ForwardingTemplates.equal_range(F);
for (auto ForwardedIt = ForwardedBegin; ForwardedIt != ForwardedEnd;
++ForwardedIt)
if (seen.find(ForwardedIt->second) == seen.end())
todo.push(ForwardedIt->second);
}
@@ -2339,12 +2367,16 @@ public:
return true;
}
// If we are in a template and find a Stmt that was registed in ForwardedTemplateLocations,
// convert the location to an actual Stmt* in ForwardingTemplates
// If we are in a template and find a Stmt that was registed in
// ForwardedTemplateLocations, convert the location to an actual Stmt* in
// ForwardingTemplates
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) {
ForwardingTemplates.insert({getCurrentFunctionTemplateInstantiation(), E});
ForwardingTemplates.insert(
{getCurrentFunctionTemplateInstantiation(), E});
return true;
}
}
@@ -2513,8 +2545,9 @@ public:
return true;
}
// If we are in a template and the new is type-dependent, register it in ForwardedTemplateLocations
// to forward its uses to the surrounding template call site
// If we are in a template and the new is type-dependent, register it in
// ForwardedTemplateLocations to forward its uses to the surrounding
// template call site
if (TemplateStack && TemplateStack->inGatherMode()) {
const auto *TypeInfo = N->getAllocatedTypeSourceInfo();
const auto ConstructExprLoc = TypeInfo->getTypeLoc().getBeginLoc();
@@ -2544,7 +2577,8 @@ public:
// Also record the dependent NestedNameSpecifier locations
for (auto NestedNameLoc = E->getQualifierLoc();
NestedNameLoc && NestedNameLoc.getNestedNameSpecifier()->isDependent();
NestedNameLoc &&
NestedNameLoc.getNestedNameSpecifier()->isDependent();
NestedNameLoc = NestedNameLoc.getPrefix()) {
TemplateStack->visitDependent(NestedNameLoc.getLocalBeginLoc());
}
@@ -2575,9 +2609,8 @@ public:
std::string symbol = std::string("URL_") + mangleURL(s);
visitIdentifier("use", "file", StringRef(s), Loc, symbol,
QualType(), Context(),
NotIdentifierToken | LocRangeEndValid);
visitIdentifier("use", "file", StringRef(s), Loc, symbol, QualType(),
Context(), NotIdentifierToken | LocRangeEndValid);
return true;
}
@@ -2592,11 +2625,11 @@ public:
std::string symbol =
std::string("FILE_") + mangleFile(newFile->Realname, type);
// We use an explicit zero-length source range at the start of the file. If we
// don't set the LocRangeEndValid flag, the visitIdentifier code will use the
// entire first token, which could be e.g. a long multiline-comment.
visitIdentifier("def", "file", newFile->Realname, SourceRange(Loc),
symbol, QualType(), Context(),
// We use an explicit zero-length source range at the start of the file. If
// we don't set the LocRangeEndValid flag, the visitIdentifier code will use
// the entire first token, which could be e.g. a long multiline-comment.
visitIdentifier("def", "file", newFile->Realname, SourceRange(Loc), symbol,
QualType(), Context(),
NotIdentifierToken | LocRangeEndValid);
}
@@ -2606,17 +2639,19 @@ public:
if (type == FileType::Unknown) {
return;
}
std::string symbol =
std::string("FILE_") + mangleFile(includedFile, type);
std::string symbol = std::string("FILE_") + mangleFile(includedFile, type);
// Support the #include MACRO use-case
// When parsing #include MACRO:
// - the filename is never passed to onTokenLexed
// - inclusionDirective is called before endMacroExpansion (which is only called when the following token is parsed)
// So add the filename here and 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.
// - inclusionDirective is called before endMacroExpansion (which is only
// called when the following token is parsed) So add the filename here and
// 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) {
MacroExpansionState->TokenLocations[FileNameRange.getBegin()] = MacroExpansionState->Expansion.length();
MacroExpansionState->TokenLocations[FileNameRange.getBegin()] =
MacroExpansionState->Expansion.length();
MacroExpansionState->Expansion += '"';
MacroExpansionState->Expansion += includedFile;
MacroExpansionState->Expansion += '"';
@@ -2640,8 +2675,8 @@ public:
IdentifierInfo *Ident = Tok.getIdentifierInfo();
if (Ident) {
std::string Mangled =
std::string("M_") + mangleLocation(Loc, std::string(Ident->getName()));
std::string Mangled = std::string("M_") +
mangleLocation(Loc, std::string(Ident->getName()));
visitIdentifier("def", "macro", Ident->getName(), Loc, Mangled);
}
}
@@ -2661,13 +2696,14 @@ public:
IdentifierInfo *Ident = Tok.getIdentifierInfo();
if (Ident) {
std::string Mangled =
std::string("M_") +
mangleLocation(Macro->getDefinitionLoc(), std::string(Ident->getName()));
std::string("M_") + mangleLocation(Macro->getDefinitionLoc(),
std::string(Ident->getName()));
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)
return;
@@ -2683,12 +2719,19 @@ public:
return;
if (MacroExpansionState) {
const auto InMacroArgs = MacroExpansionState->Range.fullyContains(SM.getExpansionRange(Range).getAsRange());
const auto InMacroBody = SM.getExpansionLoc(Tok.getLocation()) == SM.getExpansionLoc(MacroExpansionState->MacroNameToken.getLocation());
const auto InMacroArgs = MacroExpansionState->Range.fullyContains(
SM.getExpansionRange(Range).getAsRange());
const auto InMacroBody =
SM.getExpansionLoc(Tok.getLocation()) ==
SM.getExpansionLoc(MacroExpansionState->MacroNameToken.getLocation());
if (InMacroArgs || InMacroBody) {
if (MacroExpansionState->MacroInfo->getDefinitionLoc() != Macro->getDefinitionLoc()) {
if (MacroExpansionState->MacroInfo->getDefinitionLoc() !=
Macro->getDefinitionLoc()) {
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);
}
@@ -2712,31 +2755,38 @@ public:
}
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 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 includedExtensions = std::array{".h", ".hpp", ".hxx", ".inc", ".def"};
const auto isIncludedFile = std::any_of(includedExtensions.begin(), includedExtensions.end(), [&](const auto *extension) {
const auto includedExtensions =
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);
});
const auto expansionReformatThreshold = isIncludedFile ? includedFileExpansionReformatThreshold : mainFileExpansionReformatThreshold;
const auto expansionReformatThreshold =
isIncludedFile ? includedFileExpansionReformatThreshold
: mainFileExpansionReformatThreshold;
if (MacroExpansionState->Expansion.length() < expansionReformatThreshold) {
// large macros are too memory-hungry to reformat with ColumnLimit != 0
// see https://github.com/llvm/llvm-project/issues/107434
auto style = clang::format::getMozillaStyle();
if (MacroExpansionState->Expansion.length() > includedFileExpansionReformatThreshold)
if (MacroExpansionState->Expansion.length() >
includedFileExpansionReformatThreshold)
style.ColumnLimit = 0;
const auto replacements = clang::format::reformat(
style,
MacroExpansionState->Expansion,
{tooling::Range(0, MacroExpansionState->Expansion.length())}
);
auto formatted = clang::tooling::applyAllReplacements(MacroExpansionState->Expansion, replacements);
style, MacroExpansionState->Expansion,
{tooling::Range(0, MacroExpansionState->Expansion.length())});
auto formatted = clang::tooling::applyAllReplacements(
MacroExpansionState->Expansion, replacements);
if (formatted) {
for (auto &[k, v] : MacroExpansionState->TokenLocations) {
v = replacements.getShiftedCodePosition(v);
@@ -2745,15 +2795,18 @@ public:
}
}
IdentifierInfo *Ident = MacroExpansionState->MacroNameToken.getIdentifierInfo();
IdentifierInfo *Ident =
MacroExpansionState->MacroNameToken.getIdentifierInfo();
std::string Symbol =
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 dependenciesEnd = MacroExpansionState->Dependencies.end();
std::sort(dependenciesBegin, dependenciesEnd);
MacroExpansionState->Dependencies.erase(std::unique(dependenciesBegin, dependenciesEnd), dependenciesEnd);
MacroExpansionState->Dependencies.erase(
std::unique(dependenciesBegin, dependenciesEnd), dependenciesEnd);
auto Key = Symbol;
for (const auto &Dependency : MacroExpansionState->Dependencies) {
@@ -2773,7 +2826,8 @@ public:
MacroExpansionState.reset();
macroUsed(MacroExpansionState->MacroNameToken, MacroExpansionState->MacroInfo);
macroUsed(MacroExpansionState->MacroNameToken,
MacroExpansionState->MacroInfo);
}
void onTokenLexed(const Token &Tok) {
@@ -2787,7 +2841,8 @@ public:
return;
}
if (ConcatInfo.AvoidConcat(MacroExpansionState->PrevPrevTok, MacroExpansionState->PrevTok, Tok)) {
if (ConcatInfo.AvoidConcat(MacroExpansionState->PrevPrevTok,
MacroExpansionState->PrevTok, Tok)) {
MacroExpansionState->Expansion += ' ';
}
@@ -2799,7 +2854,8 @@ public:
} else {
const auto spelling = CI.getPreprocessor().getSpelling(Tok);
if (Tok.isAnyIdentifier()) {
MacroExpansionState->TokenLocations[SLoc] = MacroExpansionState->Expansion.length();
MacroExpansionState->TokenLocations[SLoc] =
MacroExpansionState->Expansion.length();
}
MacroExpansionState->Expansion += spelling;
}
@@ -2826,11 +2882,9 @@ void PreprocessorHook::FileChanged(SourceLocation Loc, FileChangeReason Reason,
}
}
void PreprocessorHook::InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
StringRef FileName,
bool IsAngled,
CharSourceRange FileNameRange,
void PreprocessorHook::InclusionDirective(
SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
bool IsAngled, CharSourceRange FileNameRange,
#if CLANG_VERSION_MAJOR >= 16
OptionalFileEntryRef File,
#elif CLANG_VERSION_MAJOR >= 15
@@ -2838,11 +2892,9 @@ void PreprocessorHook::InclusionDirective(SourceLocation HashLoc,
#else
const FileEntry *File,
#endif
StringRef SearchPath,
StringRef RelativePath,
StringRef SearchPath, StringRef RelativePath,
#if CLANG_VERSION_MAJOR >= 19
const Module *SuggestedModule,
bool ModuleImported,
const Module *SuggestedModule, bool ModuleImported,
#else
const Module *Imported,
#endif
@@ -2851,7 +2903,8 @@ void PreprocessorHook::InclusionDirective(SourceLocation HashLoc,
if (!File) {
return;
}
Indexer->inclusionDirective(FileNameRange.getAsRange(), &File->getFileEntry());
Indexer->inclusionDirective(FileNameRange.getAsRange(),
&File->getFileEntry());
#else
Indexer->inclusionDirective(FileNameRange.getAsRange(), File);
#endif
@@ -2869,8 +2922,7 @@ void PreprocessorHook::MacroExpands(const Token &Tok, const MacroDefinition &Md,
void PreprocessorHook::MacroUndefined(const Token &Tok,
const MacroDefinition &Md,
const MacroDirective *Undef)
{
const MacroDirective *Undef) {
Indexer->macroUsed(Tok, Md.getMacroInfo());
}

View File

@@ -37,6 +37,4 @@ std::string hash(const std::string &Str) {
return std::string(HashStr);
}
std::string toString(int N) {
return stringFormat("%d", N);
}
std::string toString(int N) { return stringFormat("%d", N); }

View File

@@ -7,8 +7,8 @@
#define StringOperations_h
#include <memory>
#include <string>
#include <string.h>
#include <string>
std::string hash(const std::string &Str);