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:
Philippe Canal 2013-09-02 23:44:24 -05:00 committed by sftnight
parent 3777a7194e
commit 53bf555194
2 changed files with 54 additions and 29 deletions

View File

@ -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);
};

View File

@ -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);
}