Some update.
This commit is contained in:
195
src/Compiler/Utility.cpp
Normal file
195
src/Compiler/Utility.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
#include <Compiler/Utility.h>
|
||||
|
||||
namespace clice {
|
||||
|
||||
bool isDefinition(const clang::Decl* decl) {
|
||||
if(auto VD = llvm::dyn_cast<clang::VarDecl>(decl)) {
|
||||
return VD->isThisDeclarationADefinition();
|
||||
}
|
||||
|
||||
if(auto FD = llvm::dyn_cast<clang::FunctionDecl>(decl)) {
|
||||
return FD->isThisDeclarationADefinition();
|
||||
}
|
||||
|
||||
if(auto TD = llvm::dyn_cast<clang::TagDecl>(decl)) {
|
||||
return TD->isThisDeclarationADefinition();
|
||||
}
|
||||
|
||||
if(llvm::isa<clang::FieldDecl,
|
||||
clang::EnumConstantDecl,
|
||||
clang::TypedefNameDecl,
|
||||
clang::ConceptDecl>(decl)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const static clang::CXXRecordDecl* getDeclContextForTemplateInstationPattern(const clang::Decl* D) {
|
||||
if(const auto* CTSD = dyn_cast<clang::ClassTemplateSpecializationDecl>(D->getDeclContext())) {
|
||||
return CTSD->getTemplateInstantiationPattern();
|
||||
}
|
||||
|
||||
if(const auto* RD = dyn_cast<clang::CXXRecordDecl>(D->getDeclContext())) {
|
||||
return RD->getInstantiatedFromMemberClass();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const clang::NamedDecl* instantiatedFrom(const clang::NamedDecl* decl) {
|
||||
if(auto CTSD = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) {
|
||||
/// If the decl is an full specialization, return itself.
|
||||
|
||||
auto kind = CTSD->getTemplateSpecializationKind();
|
||||
if(kind == clang::TSK_Undeclared || kind == clang::TSK_ExplicitSpecialization) {
|
||||
return CTSD;
|
||||
}
|
||||
|
||||
auto CRD = CTSD->getTemplateInstantiationPattern();
|
||||
assert(CRD && "Unexpected template instantiation pattern");
|
||||
|
||||
/// Primary template.
|
||||
if(auto CTD = CRD->getDescribedClassTemplate()) {
|
||||
return CTD;
|
||||
}
|
||||
|
||||
/// Partial specialization.
|
||||
return CRD;
|
||||
}
|
||||
|
||||
if(auto FD = llvm::dyn_cast<clang::FunctionDecl>(decl)) {
|
||||
/// If the decl is an full specialization, return itself.
|
||||
if(FD->getTemplateSpecializationKind() == clang::TSK_ExplicitSpecialization) {
|
||||
return FD;
|
||||
}
|
||||
|
||||
return FD->getTemplateInstantiationPattern();
|
||||
}
|
||||
|
||||
if(auto VD = llvm::dyn_cast<clang::VarDecl>(decl)) {
|
||||
/// If the decl is an full specialization, return itself.
|
||||
if(VD->getTemplateSpecializationKind() == clang::TSK_ExplicitSpecialization) {
|
||||
return VD;
|
||||
}
|
||||
|
||||
return VD->getTemplateInstantiationPattern();
|
||||
}
|
||||
|
||||
if(auto CRD = llvm::dyn_cast<clang::CXXRecordDecl>(decl)) {
|
||||
if(auto CTD = CRD->getDescribedClassTemplate()) {
|
||||
return CTD;
|
||||
}
|
||||
|
||||
return CRD->getInstantiatedFromMemberClass();
|
||||
}
|
||||
|
||||
/// For `FieldDecl` and `TypedefNameDecl`, clang will not store their instantiation information
|
||||
/// in the AST. So we need to look up the original decl manually.
|
||||
if(llvm::isa<clang::FieldDecl, clang::TypedefNameDecl>(decl)) {
|
||||
/// FIXME: figure out the context.
|
||||
if(auto context = getDeclContextForTemplateInstationPattern(decl)) {
|
||||
for(auto member: context->lookup(decl->getDeclName())) {
|
||||
if(member->isImplicit()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(member->getKind() == decl->getKind()) {
|
||||
return member;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(auto ED = llvm::dyn_cast<clang::EnumDecl>(decl)) {
|
||||
return ED->getInstantiatedFromMemberEnum();
|
||||
}
|
||||
|
||||
if(auto ECD = llvm::dyn_cast<clang::EnumConstantDecl>(decl)) {
|
||||
auto ED = llvm::cast<clang::EnumDecl>(ECD->getDeclContext());
|
||||
if(auto context = ED->getInstantiatedFromMemberEnum()) {
|
||||
for(auto member: context->lookup(ECD->getDeclName())) {
|
||||
return member;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
clang::QualType typeForDecl(const clang::NamedDecl* decl) {
|
||||
if(auto VD = llvm::dyn_cast<clang::VarDecl>(decl)) {
|
||||
return VD->getType();
|
||||
}
|
||||
|
||||
if(auto FD = llvm::dyn_cast<clang::FieldDecl>(decl)) {
|
||||
return FD->getType();
|
||||
}
|
||||
|
||||
if(auto ECD = llvm::dyn_cast<clang::EnumConstantDecl>(decl)) {
|
||||
return ECD->getType();
|
||||
}
|
||||
|
||||
if(auto BD = llvm::dyn_cast<clang::BindingDecl>(decl)) {
|
||||
return BD->getType();
|
||||
}
|
||||
|
||||
if(auto TD = llvm::dyn_cast<clang::TypedefNameDecl>(decl)) {
|
||||
return TD->getUnderlyingType();
|
||||
}
|
||||
|
||||
if(auto CCD = llvm::dyn_cast<clang::CXXConstructorDecl>(decl)) {
|
||||
return CCD->getThisType();
|
||||
}
|
||||
|
||||
if(auto CDD = llvm::dyn_cast<clang::CXXDestructorDecl>(decl)) {
|
||||
return CDD->getThisType();
|
||||
}
|
||||
|
||||
return clang::QualType();
|
||||
}
|
||||
|
||||
const clang::NamedDecl* declForType(clang::QualType type) {
|
||||
if(type.isNull()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(auto RT = llvm::dyn_cast<clang::TagType>(type)) {
|
||||
return RT->getDecl();
|
||||
}
|
||||
|
||||
if(auto TT = llvm::dyn_cast<clang::TypedefType>(type)) {
|
||||
return TT->getDecl();
|
||||
}
|
||||
|
||||
/// FIXME:
|
||||
if(auto TST = llvm::dyn_cast<clang::TemplateSpecializationType>(type)) {
|
||||
auto decl = TST->getTemplateName().getAsTemplateDecl();
|
||||
if(type->isDependentType()) {
|
||||
return decl;
|
||||
}
|
||||
|
||||
/// For a template specialization type, the template name is possibly a `ClassTemplateDecl`
|
||||
/// `TypeAliasTemplateDecl` or `TemplateTemplateParmDecl` and `BuiltinTemplateDecl`.
|
||||
|
||||
if(llvm::isa<clang::TemplateTemplateParmDecl,
|
||||
clang::TypeAliasTemplateDecl,
|
||||
clang::BuiltinTemplateDecl>(decl)) {
|
||||
return decl;
|
||||
}
|
||||
|
||||
return instantiatedFrom(TST->getAsCXXRecordDecl());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void dumpInclude(clang::SourceManager& srcMgr, clang::SourceLocation loc) {
|
||||
auto file = srcMgr.getFileID(loc);
|
||||
for(auto includeLoc = srcMgr.getIncludeLoc(file); includeLoc.isValid();
|
||||
includeLoc = srcMgr.getIncludeLoc(file)) {
|
||||
includeLoc.dump(srcMgr);
|
||||
file = srcMgr.getFileID(includeLoc);
|
||||
}
|
||||
}
|
||||
} // namespace clice
|
||||
Reference in New Issue
Block a user