In GetPartiallyDesugaredType add ability to replace a type by a typedef.
Add struct cling::utils::Transform::Config to hold both the list of typedef to avoid desugaring (m_toSkip) and the list of type to replace by a nicer typedef (m_toReplace). This is used to replace basic_string<...> by std::string.
This commit is contained in:
parent
3777a7194e
commit
53bf555194
@ -8,6 +8,7 @@
|
||||
#define CLING_UTILS_AST_H
|
||||
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
@ -106,6 +107,20 @@ namespace utils {
|
||||
class Transform {
|
||||
public:
|
||||
|
||||
///\brief Class containing the information on how to configure the
|
||||
/// transformation
|
||||
///
|
||||
struct Config {
|
||||
typedef const clang::Type cType;
|
||||
typedef llvm::SmallSet<cType*, 4> SkipCollection;
|
||||
typedef llvm::DenseMap<cType*, cType*> ReplaceCollection;
|
||||
|
||||
SkipCollection m_toSkip;
|
||||
ReplaceCollection m_toReplace;
|
||||
|
||||
bool empty() const { return m_toSkip.size()==0 && m_toReplace.empty(); }
|
||||
};
|
||||
|
||||
///\brief Remove one layer of sugar, but only some kinds.
|
||||
static bool SingleStepPartiallyDesugarType(clang::QualType& QT,
|
||||
const clang::ASTContext& C);
|
||||
@ -124,7 +139,7 @@ namespace utils {
|
||||
static
|
||||
clang::QualType
|
||||
GetPartiallyDesugaredType(const clang::ASTContext& Ctx, clang::QualType QT,
|
||||
const llvm::SmallSet<const clang::Type*, 4>& TypesToSkip,
|
||||
const Config& TypeConfig,
|
||||
bool fullyQualify = true);
|
||||
|
||||
};
|
||||
|
@ -23,14 +23,14 @@ namespace utils {
|
||||
static
|
||||
QualType GetPartiallyDesugaredTypeImpl(const ASTContext& Ctx,
|
||||
QualType QT,
|
||||
const llvm::SmallSet<const Type*,4>& TypesToSkip,
|
||||
const Transform::Config& TypeConfig,
|
||||
bool fullyQualifyType,
|
||||
bool fullyQualifyTmpltArg);
|
||||
|
||||
static
|
||||
NestedNameSpecifier* GetPartiallyDesugaredNNS(const ASTContext& Ctx,
|
||||
NestedNameSpecifier* scope,
|
||||
const llvm::SmallSet<const Type*, 4>& TypesToSkip);
|
||||
const Transform::Config& TypeConfig);
|
||||
|
||||
bool Analyze::IsWrapper(const NamedDecl* ND) {
|
||||
if (!ND)
|
||||
@ -266,7 +266,7 @@ namespace utils {
|
||||
NestedNameSpecifier* SelectPrefix(const ASTContext& Ctx,
|
||||
const DeclContext *declContext,
|
||||
NestedNameSpecifier *original_prefix,
|
||||
const llvm::SmallSet<const Type*,4>& TypesToSkip) {
|
||||
const Transform::Config& TypeConfig) {
|
||||
// We have to also desugar the prefix.
|
||||
|
||||
NestedNameSpecifier* prefix = 0;
|
||||
@ -312,7 +312,7 @@ namespace utils {
|
||||
{
|
||||
// This is the same type, use the original prefix as a starting
|
||||
// point.
|
||||
prefix = GetPartiallyDesugaredNNS(Ctx,original_prefix,TypesToSkip);
|
||||
prefix = GetPartiallyDesugaredNNS(Ctx,original_prefix,TypeConfig);
|
||||
} else {
|
||||
const TagDecl *tdecl = dyn_cast<TagDecl>(declContext);
|
||||
if (tdecl) {
|
||||
@ -339,7 +339,7 @@ namespace utils {
|
||||
NestedNameSpecifier* SelectPrefix(const ASTContext& Ctx,
|
||||
const ElaboratedType *etype,
|
||||
NestedNameSpecifier *original_prefix,
|
||||
const llvm::SmallSet<const Type*,4>& TypesToSkip) {
|
||||
const Transform::Config& TypeConfig) {
|
||||
// We have to also desugar the prefix.
|
||||
|
||||
NestedNameSpecifier* prefix = etype->getQualifier();
|
||||
@ -357,9 +357,9 @@ namespace utils {
|
||||
{
|
||||
// This is the same type, use the original prefix as a starting
|
||||
// point.
|
||||
prefix = GetPartiallyDesugaredNNS(Ctx,original_prefix,TypesToSkip);
|
||||
prefix = GetPartiallyDesugaredNNS(Ctx,original_prefix,TypeConfig);
|
||||
} else {
|
||||
prefix = GetPartiallyDesugaredNNS(Ctx,prefix,TypesToSkip);
|
||||
prefix = GetPartiallyDesugaredNNS(Ctx,prefix,TypeConfig);
|
||||
}
|
||||
} else {
|
||||
// Deal with namespace. This is mostly about dealing with
|
||||
@ -399,9 +399,9 @@ namespace utils {
|
||||
|
||||
|
||||
static
|
||||
NestedNameSpecifier* GetPartiallyDesugaredNNS(const ASTContext& Ctx,
|
||||
NestedNameSpecifier* GetPartiallyDesugaredNNS(const ASTContext& Ctx,
|
||||
NestedNameSpecifier* scope,
|
||||
const llvm::SmallSet<const Type*, 4>& TypesToSkip){
|
||||
const Transform::Config& TypeConfig) {
|
||||
// Desugar the scope qualifier if needed.
|
||||
|
||||
if (const Type* scope_type = scope->getAsType()) {
|
||||
@ -409,7 +409,7 @@ namespace utils {
|
||||
// this is not a namespace, so we might need to desugar
|
||||
QualType desugared = GetPartiallyDesugaredTypeImpl(Ctx,
|
||||
QualType(scope_type,0),
|
||||
TypesToSkip,
|
||||
TypeConfig,
|
||||
/*qualifyType=*/false,
|
||||
/*qualifyTmpltArg=*/true);
|
||||
|
||||
@ -422,10 +422,10 @@ namespace utils {
|
||||
// looking a typedef pointing at a (or another) scope.
|
||||
|
||||
if (outer_scope) {
|
||||
outer_scope = SelectPrefix(Ctx,etype,outer_scope,TypesToSkip);
|
||||
outer_scope = SelectPrefix(Ctx,etype,outer_scope,TypeConfig);
|
||||
} else {
|
||||
outer_scope = GetPartiallyDesugaredNNS(Ctx,etype->getQualifier(),
|
||||
TypesToSkip);
|
||||
TypeConfig);
|
||||
}
|
||||
desugared = etype->getNamedType();
|
||||
} else {
|
||||
@ -453,12 +453,12 @@ namespace utils {
|
||||
&& !(outer_ns && outer_ns->isAnonymousNamespace())
|
||||
&& outer->getName().size() ) {
|
||||
outer_scope = SelectPrefix(Ctx,decl->getDeclContext(),
|
||||
outer_scope,TypesToSkip);
|
||||
outer_scope,TypeConfig);
|
||||
} else {
|
||||
outer_scope = 0;
|
||||
}
|
||||
} else if (outer_scope) {
|
||||
outer_scope = GetPartiallyDesugaredNNS(Ctx, outer_scope, TypesToSkip);
|
||||
outer_scope = GetPartiallyDesugaredNNS(Ctx, outer_scope, TypeConfig);
|
||||
}
|
||||
}
|
||||
return NestedNameSpecifier::Create(Ctx,outer_scope,
|
||||
@ -492,7 +492,7 @@ namespace utils {
|
||||
{
|
||||
// Return true, if we should keep this typedef rather than desugaring it.
|
||||
|
||||
if ( 0 != TypesToSkip.count(QT.getTypePtr()) )
|
||||
if ( 0 != TypesToSkip.count(QT.getTypePtr()) )
|
||||
return true;
|
||||
|
||||
const TypedefType* typedeftype =
|
||||
@ -644,12 +644,12 @@ namespace utils {
|
||||
}
|
||||
|
||||
static QualType GetPartiallyDesugaredTypeImpl(const ASTContext& Ctx,
|
||||
QualType QT, const llvm::SmallSet<const Type*,4>& TypesToSkip,
|
||||
QualType QT, const Transform::Config& TypeConfig,
|
||||
bool fullyQualifyType,
|
||||
bool fullyQualifyTmpltArg)
|
||||
{
|
||||
// If there are no constraints, then use the standard desugaring.
|
||||
if (!TypesToSkip.size() && !fullyQualifyType && !fullyQualifyTmpltArg)
|
||||
if (TypeConfig.empty() && !fullyQualifyType && !fullyQualifyTmpltArg)
|
||||
return QT.getDesugaredType(Ctx);
|
||||
|
||||
// In case of Int_t* we need to strip the pointer first, desugar and attach
|
||||
@ -657,7 +657,7 @@ namespace utils {
|
||||
if (isa<PointerType>(QT.getTypePtr())) {
|
||||
// Get the qualifiers.
|
||||
Qualifiers quals = QT.getQualifiers();
|
||||
QT = GetPartiallyDesugaredTypeImpl(Ctx, QT->getPointeeType(), TypesToSkip,
|
||||
QT = GetPartiallyDesugaredTypeImpl(Ctx, QT->getPointeeType(), TypeConfig,
|
||||
fullyQualifyType,fullyQualifyTmpltArg);
|
||||
QT = Ctx.getPointerType(QT);
|
||||
// Add back the qualifiers.
|
||||
@ -681,7 +681,7 @@ namespace utils {
|
||||
// Get the qualifiers.
|
||||
bool isLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
|
||||
Qualifiers quals = QT.getQualifiers();
|
||||
QT = GetPartiallyDesugaredTypeImpl(Ctx, QT->getPointeeType(), TypesToSkip,
|
||||
QT = GetPartiallyDesugaredTypeImpl(Ctx, QT->getPointeeType(), TypeConfig,
|
||||
fullyQualifyType,fullyQualifyTmpltArg);
|
||||
// Add the r- or l-value reference type back to the desugared one.
|
||||
if (isLValueRefTy)
|
||||
@ -731,7 +731,7 @@ namespace utils {
|
||||
// we hit one of the special typedefs.
|
||||
while (1) {
|
||||
if (llvm::isa<TypedefType>(QT.getTypePtr()) &&
|
||||
ShouldKeepTypedef(QT, TypesToSkip)) {
|
||||
ShouldKeepTypedef(QT, TypeConfig.m_toSkip)) {
|
||||
if (!fullyQualifyType && !fullyQualifyTmpltArg) {
|
||||
return QT;
|
||||
}
|
||||
@ -740,6 +740,16 @@ namespace utils {
|
||||
break;
|
||||
}
|
||||
bool wasDesugared = Transform::SingleStepPartiallyDesugarType(QT,Ctx);
|
||||
|
||||
// Did we get to a basic_string, let's get back to std::string
|
||||
Transform::Config::ReplaceCollection::const_iterator
|
||||
iter = TypeConfig.m_toReplace.find(QT.getTypePtr());
|
||||
if (iter != TypeConfig.m_toReplace.end()) {
|
||||
Qualifiers quals = QT.getQualifiers();
|
||||
QT = clang::QualType( iter->second, 0);
|
||||
QT = Ctx.getQualifiedType(QT,quals);
|
||||
break;
|
||||
}
|
||||
if (!wasDesugared) {
|
||||
// No more work to do, stop now.
|
||||
break;
|
||||
@ -750,7 +760,7 @@ namespace utils {
|
||||
// desugar what they point to.
|
||||
if (isa<PointerType>(QT.getTypePtr()) ||
|
||||
isa<ReferenceType>(QT.getTypePtr()) ) {
|
||||
return GetPartiallyDesugaredTypeImpl(Ctx, QT, TypesToSkip,
|
||||
return GetPartiallyDesugaredTypeImpl(Ctx, QT, TypeConfig,
|
||||
fullyQualifyType,
|
||||
fullyQualifyTmpltArg);
|
||||
}
|
||||
@ -760,7 +770,7 @@ namespace utils {
|
||||
= dyn_cast<ElaboratedType>(QT.getTypePtr());
|
||||
if (etype) {
|
||||
|
||||
prefix = SelectPrefix(Ctx,etype,original_prefix,TypesToSkip);
|
||||
prefix = SelectPrefix(Ctx,etype,original_prefix,TypeConfig);
|
||||
|
||||
prefix_qualifiers.addQualifiers(QT.getLocalQualifiers());
|
||||
QT = QualType(etype->getNamedType().getTypePtr(),0);
|
||||
@ -798,7 +808,7 @@ namespace utils {
|
||||
if (oldtype) {
|
||||
if (oldtype->getAsCXXRecordDecl() == outer) {
|
||||
// Same type, use the original spelling
|
||||
prefix = GetPartiallyDesugaredNNS(Ctx,original_prefix,TypesToSkip);
|
||||
prefix = GetPartiallyDesugaredNNS(Ctx,original_prefix,TypeConfig);
|
||||
outer = 0; // Cancel the later creation.
|
||||
}
|
||||
} else {
|
||||
@ -836,7 +846,7 @@ namespace utils {
|
||||
TagDecl *tdecl = dyn_cast<TagDecl>(outer);
|
||||
if (tdecl) {
|
||||
prefix = CreateNestedNameSpecifier(Ctx,tdecl);
|
||||
prefix = GetPartiallyDesugaredNNS(Ctx,prefix,TypesToSkip);
|
||||
prefix = GetPartiallyDesugaredNNS(Ctx,prefix,TypeConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -867,7 +877,7 @@ namespace utils {
|
||||
mightHaveChanged = true;
|
||||
desArgs.push_back(TemplateArgument(GetPartiallyDesugaredTypeImpl(Ctx,
|
||||
SubTy,
|
||||
TypesToSkip,
|
||||
TypeConfig,
|
||||
fullyQualifyType,
|
||||
fullyQualifyTmpltArg)));
|
||||
} else
|
||||
@ -916,7 +926,7 @@ namespace utils {
|
||||
desArgs.push_back(TemplateArgument(
|
||||
GetPartiallyDesugaredTypeImpl(Ctx,
|
||||
SubTy,
|
||||
TypesToSkip,
|
||||
TypeConfig,
|
||||
/*fullyQualifyType=*/true,
|
||||
/*fullyQualifyTmpltArg=*/true)));
|
||||
} else
|
||||
@ -945,10 +955,10 @@ namespace utils {
|
||||
}
|
||||
|
||||
QualType Transform::GetPartiallyDesugaredType(const ASTContext& Ctx,
|
||||
QualType QT, const llvm::SmallSet<const Type*,4>& TypesToSkip,
|
||||
QualType QT, const Transform::Config& TypeConfig,
|
||||
bool fullyQualify/*=true*/)
|
||||
{
|
||||
return GetPartiallyDesugaredTypeImpl(Ctx,QT,TypesToSkip,
|
||||
return GetPartiallyDesugaredTypeImpl(Ctx,QT,TypeConfig,
|
||||
/*qualifyType*/fullyQualify,
|
||||
/*qualifyTmpltArg*/fullyQualify);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user