#include "data/parser/cxx/utilityCxx.h" #include #include #include #include "data/type/DataType.h" #include "data/type/modifier/DataTypeModifierArray.h" #include "data/type/modifier/DataTypeModifierPointer.h" #include "data/type/modifier/DataTypeModifierReference.h" #include "data/type/DataTypeModifierStack.h" #include "data/type/DataTypeQualifierList.h" #include "utility/utilityString.h" #include "utility/logging/logging.h" namespace utility { DataType qualTypeToDataType(clang::QualType qualType) { std::vector typeNameHerarchy; DataTypeQualifierList qualifierList; DataTypeModifierStack modifierStack; while (true) { const clang::Type* type = qualType.getTypePtr(); if (type->getAs()) { typeNameHerarchy.push_back(utility::substrAfter(qualType.getAsString(), ' ')); break; } else if (type->isPointerType()) { std::shared_ptr modifier = std::make_shared(); if (qualType.isConstQualified()) { modifier->addQualifier(DataTypeQualifierList::QUALIFIER_CONST); } modifierStack.push(modifier); qualType = type->getPointeeType(); } else if (type->isArrayType()) { std::shared_ptr modifier = std::make_shared(); if (qualType.isConstQualified()) { modifier->addQualifier(DataTypeQualifierList::QUALIFIER_CONST); } modifierStack.push(modifier); qualType = clang::dyn_cast(type)->getElementType(); } else if (type->isReferenceType()) { std::shared_ptr modifier = std::make_shared(); // references can not be const qualified modifierStack.push(modifier); qualType = type->getPointeeType(); } else { const clang::Type* type = qualType.getUnqualifiedType().getTypePtr(); if (clang::isa(type)) { typeNameHerarchy = getDeclNameHierarchy(clang::dyn_cast(type)->getDecl()); } else { clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions()); pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A" pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool" std::string typeName = qualType.getUnqualifiedType().getAsString(pp); if (type->isTemplateTypeParmType()) { clang::TemplateTypeParmDecl* templateTypeParmDecl = clang::dyn_cast(qualType.getUnqualifiedType())->getDecl(); if (templateTypeParmDecl) { typeNameHerarchy = getContextNameHierarchy(templateTypeParmDecl->getDeclContext()); typeNameHerarchy.back() += "::" + typeName; } } else { typeNameHerarchy.push_back(typeName); } } break; } } if (qualType.isConstQualified()) { qualifierList.addQualifier(DataTypeQualifierList::QUALIFIER_CONST); } return DataType(typeNameHerarchy, qualifierList, modifierStack); } std::vector getDeclNameHierarchy(clang::Decl* declaration) { std::string declName = ""; if (clang::isa(declaration)) { declName = getDeclName(clang::dyn_cast(declaration)); } else { LOG_ERROR("unhandled declaration type"); } std::vector contextNameHierarchy = getContextNameHierarchy(declaration->getDeclContext()); contextNameHierarchy.push_back(declName); return contextNameHierarchy; } std::vector getContextNameHierarchy(clang::DeclContext* declContext) { std::vector contextNameHierarchy; clang::DeclContext* parentContext = declContext->getParent(); if (parentContext) { contextNameHierarchy = getContextNameHierarchy(parentContext); } if (clang::isa(declContext)) { std::string declName = getDeclName(clang::dyn_cast(declContext)); if (declName != "") { contextNameHierarchy.push_back(declName); } } return contextNameHierarchy; } std::string getDeclName(clang::NamedDecl* declaration) { std::string declName = declaration->getNameAsString(); if (clang::isa(declaration)) { clang::ClassTemplateDecl* templateClassDeclaration = clang::dyn_cast(declaration)->getDescribedClassTemplate(); if (templateClassDeclaration) { declName = getDeclName(templateClassDeclaration); } else if (clang::isa(declaration)) { std::string specializedParameterNamePart = "<"; const clang::TemplateArgumentList& templateArgumentList = clang::dyn_cast(declaration)->getTemplateArgs(); for (size_t i = 0; i < templateArgumentList.size(); i++) { DataType datatype = utility::qualTypeToDataType(templateArgumentList.get(i).getAsType()); specializedParameterNamePart += datatype.getFullTypeName(); specializedParameterNamePart += (i < templateArgumentList.size() - 1) ? ", " : ""; } specializedParameterNamePart += ">"; declName += specializedParameterNamePart; } } else if (clang::isa(declaration)) { std::string templateParameterNamePart = "<"; clang::TemplateParameterList* parameterList = clang::dyn_cast(declaration)->getTemplateParameters(); for (size_t i = 0; i < parameterList->size(); i++) { clang::NamedDecl* namedDecl = parameterList->getParam(i); templateParameterNamePart += namedDecl->getNameAsString(); templateParameterNamePart += (i < parameterList->size() - 1) ? ", " : ""; } templateParameterNamePart += ">"; declName += templateParameterNamePart; } else if (clang::isa(declaration) && clang::dyn_cast(declaration)->isAnonymousNamespace()) { declName = "(anonymous namespace)"; } return declName; } }