#include "Util.h"
#include <algorithm>
#include "clang/AST/Decl.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
namespace raw_ptr_plugin {
namespace {
const char* kTreatAsThirdPartyDirs[] = {
"/breakpad/",
"/courgette/",
"/frameworks/",
"/native_client/",
"/ppapi/",
"/testing/",
"/v8/",
};
std::string GetNamespaceImpl(const clang::DeclContext* context,
const std::string& candidate) {
switch (context->getDeclKind()) {
case clang::Decl::TranslationUnit: {
return candidate;
}
case clang::Decl::Namespace: {
const auto* decl = llvm::dyn_cast<clang::NamespaceDecl>(context);
std::string name_str;
llvm::raw_string_ostream OS(name_str);
if (decl->isAnonymousNamespace()) {
OS << "<anonymous namespace>";
} else {
OS << *decl;
}
return GetNamespaceImpl(context->getParent(), OS.str());
}
default: {
return GetNamespaceImpl(context->getParent(), candidate);
}
}
}
}
std::string GetNamespace(const clang::Decl* record) {
return GetNamespaceImpl(record->getDeclContext(), std::string());
}
std::string GetFilename(const clang::SourceManager& source_manager,
clang::SourceLocation loc,
FilenameLocationType type,
FilenamesFollowPresumed follow_presumed) {
switch (type) {
case FilenameLocationType::kExactLoc:
break;
case FilenameLocationType::kSpellingLoc:
loc = source_manager.getSpellingLoc(loc);
break;
case FilenameLocationType::kExpansionLoc:
loc = source_manager.getExpansionLoc(loc);
break;
}
std::string name;
if (follow_presumed == FilenamesFollowPresumed::kYes) {
clang::PresumedLoc ploc = source_manager.getPresumedLoc(loc);
if (ploc.isInvalid()) {
return name;
}
name = ploc.getFilename();
} else {
name = source_manager.getFilename(loc);
}
std::replace(name.begin(), name.end(), '\\', '/');
return name;
}
LocationClassification ClassifySourceLocation(
const clang::HeaderSearchOptions& search,
const clang::SourceManager& sm,
clang::SourceLocation loc) {
if (sm.isInSystemHeader(loc)) {
return LocationClassification::kSystem;
}
std::string filename = GetFilename(sm, loc, FilenameLocationType::kExactLoc);
if (filename.empty()) {
return LocationClassification::kThirdParty;
}
if (!search.Sysroot.empty() && search.Sysroot != "/" &&
llvm::StringRef(filename).starts_with(search.Sysroot)) {
return LocationClassification::kSystem;
}
if (filename == "<scratch space>") {
return LocationClassification::kMacro;
}
if (filename.front() != '/') {
filename.insert(0, 1, '/');
}
if (filename.find("/gen/") != std::string::npos) {
return LocationClassification::kGenerated;
}
if (auto p = filename.find("/third_party/blink/"); p != std::string::npos) {
if (!llvm::StringRef(filename).substr(p).starts_with("browser/")) {
return LocationClassification::kBlink;
}
}
if (filename.find("/third_party/") != std::string::npos) {
return LocationClassification::kThirdParty;
}
for (const char* dir : kTreatAsThirdPartyDirs) {
if (filename.find(dir) != std::string::npos) {
return LocationClassification::kThirdParty;
}
}
return LocationClassification::kFirstParty;
}
}