Fix ROOT-5442, wrong normalization of std::vector<myNamespace::myClass1*>::const_iterator

GetPartiallyDesugaredType was 'forgetting' to add full qualification of the
template parameters in some case (where the template paramter in the
QualType was not yet an elaborated type).  Extend the internal interface to
distinguish when we need to add full qualification to the type itself or its
template parameters.
This commit is contained in:
Philippe Canal 2013-08-28 17:02:57 -05:00 committed by sftnight
parent f127f8797f
commit 52da28145b
2 changed files with 65 additions and 34 deletions

View File

@ -20,6 +20,18 @@ using namespace clang;
namespace cling {
namespace utils {
static
QualType GetPartiallyDesugaredTypeImpl(const ASTContext& Ctx,
QualType QT,
const llvm::SmallSet<const Type*,4>& TypesToSkip,
bool fullyQualifyType,
bool fullyQualifyTmpltArg);
static
NestedNameSpecifier* GetPartiallyDesugaredNNS(const ASTContext& Ctx,
NestedNameSpecifier* scope,
const llvm::SmallSet<const Type*, 4>& TypesToSkip);
bool Analyze::IsWrapper(const NamedDecl* ND) {
if (!ND)
return false;
@ -168,11 +180,6 @@ namespace utils {
}
}
static
NestedNameSpecifier* GetPartiallyDesugaredNNS(const ASTContext& Ctx,
NestedNameSpecifier* scope,
const llvm::SmallSet<const Type*, 4>& TypesToSkip);
static
NestedNameSpecifier* GetFullyQualifiedNameSpecifier(const ASTContext& Ctx,
NestedNameSpecifier* scope) {
@ -400,11 +407,11 @@ namespace utils {
if (const Type* scope_type = scope->getAsType()) {
// this is not a namespace, so we might need to desugar
QualType desugared =
Transform::GetPartiallyDesugaredType(Ctx,
QualType(scope_type,0),
TypesToSkip,
/*fullyQualify=*/false);
QualType desugared = GetPartiallyDesugaredTypeImpl(Ctx,
QualType(scope_type,0),
TypesToSkip,
/*qualifyType=*/false,
/*qualifyTmpltArg=*/true);
NestedNameSpecifier* outer_scope = scope->getPrefix();
const ElaboratedType* etype
@ -636,12 +643,13 @@ namespace utils {
return desugared;
}
QualType Transform::GetPartiallyDesugaredType(const ASTContext& Ctx,
static QualType GetPartiallyDesugaredTypeImpl(const ASTContext& Ctx,
QualType QT, const llvm::SmallSet<const Type*,4>& TypesToSkip,
bool fullyQualify/*=true*/)
bool fullyQualifyType,
bool fullyQualifyTmpltArg)
{
// If there are no constraints, then use the standard desugaring.
if (!TypesToSkip.size() && !fullyQualify)
if (!TypesToSkip.size() && !fullyQualifyType && !fullyQualifyTmpltArg)
return QT.getDesugaredType(Ctx);
// In case of Int_t* we need to strip the pointer first, desugar and attach
@ -649,8 +657,8 @@ namespace utils {
if (isa<PointerType>(QT.getTypePtr())) {
// Get the qualifiers.
Qualifiers quals = QT.getQualifiers();
QT = GetPartiallyDesugaredType(Ctx, QT->getPointeeType(), TypesToSkip,
fullyQualify);
QT = GetPartiallyDesugaredTypeImpl(Ctx, QT->getPointeeType(), TypesToSkip,
fullyQualifyType,fullyQualifyTmpltArg);
QT = Ctx.getPointerType(QT);
// Add back the qualifiers.
QT = Ctx.getQualifiedType(QT, quals);
@ -673,8 +681,8 @@ namespace utils {
// Get the qualifiers.
bool isLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
Qualifiers quals = QT.getQualifiers();
QT = GetPartiallyDesugaredType(Ctx, QT->getPointeeType(), TypesToSkip,
fullyQualify);
QT = GetPartiallyDesugaredTypeImpl(Ctx, QT->getPointeeType(), TypesToSkip,
fullyQualifyType,fullyQualifyTmpltArg);
// Add the r- or l-value reference type back to the desugared one.
if (isLValueRefTy)
QT = Ctx.getLValueReferenceType(QT);
@ -710,7 +718,7 @@ namespace utils {
if (!(ns && ns->isAnonymousNamespace())) {
// We have to also desugar the prefix unless
// it does not have a name (anonymous namespaces).
fullyQualify = true;
fullyQualifyType = true;
prefix_qualifiers = QT.getLocalQualifiers();
QT = QualType(etype_input->getNamedType().getTypePtr(),0);
} else {
@ -724,14 +732,14 @@ namespace utils {
while (1) {
if (llvm::isa<TypedefType>(QT.getTypePtr()) &&
ShouldKeepTypedef(QT, TypesToSkip)) {
if (!fullyQualify) {
if (!fullyQualifyType && !fullyQualifyTmpltArg) {
return QT;
}
// We might have stripped the namespace/scope part,
// so we must go on to add it back.
break;
}
bool wasDesugared = SingleStepPartiallyDesugarType(QT,Ctx);
bool wasDesugared = Transform::SingleStepPartiallyDesugarType(QT,Ctx);
if (!wasDesugared) {
// No more work to do, stop now.
break;
@ -742,8 +750,9 @@ namespace utils {
// desugar what they point to.
if (isa<PointerType>(QT.getTypePtr()) ||
isa<ReferenceType>(QT.getTypePtr()) ) {
return GetPartiallyDesugaredType(Ctx, QT, TypesToSkip,
fullyQualify);
return GetPartiallyDesugaredTypeImpl(Ctx, QT, TypesToSkip,
fullyQualifyType,
fullyQualifyTmpltArg);
}
NestedNameSpecifier* prefix = 0;
@ -756,7 +765,7 @@ namespace utils {
prefix_qualifiers.addQualifiers(QT.getLocalQualifiers());
QT = QualType(etype->getNamedType().getTypePtr(),0);
} else if (fullyQualify) {
} else if (fullyQualifyType) {
// Let's check whether this type should have been an elaborated type.
// in which case we want to add it ... but we can't really preserve
// the typedef in this case ...
@ -827,6 +836,7 @@ namespace utils {
TagDecl *tdecl = dyn_cast<TagDecl>(outer);
if (tdecl) {
prefix = CreateNestedNameSpecifier(Ctx,tdecl);
prefix = GetPartiallyDesugaredNNS(Ctx,prefix,TypesToSkip);
}
}
}
@ -853,13 +863,14 @@ namespace utils {
if (isa<TypedefType>(SubTy)
|| isa<TemplateSpecializationType>(SubTy)
|| isa<ElaboratedType>(SubTy)
|| fullyQualify) {
|| fullyQualifyTmpltArg) {
mightHaveChanged = true;
desArgs.push_back(TemplateArgument(GetPartiallyDesugaredType(Ctx,
desArgs.push_back(TemplateArgument(GetPartiallyDesugaredTypeImpl(Ctx,
SubTy,
TypesToSkip,
fullyQualify)));
} else
TypesToSkip,
fullyQualifyType,
fullyQualifyTmpltArg)));
} else
desArgs.push_back(*I);
}
@ -872,7 +883,7 @@ namespace utils {
TST->getCanonicalTypeInternal());
QT = Ctx.getQualifiedType(QT, qualifiers);
}
} else if (fullyQualify) {
} else if (fullyQualifyTmpltArg) {
if (const RecordType *TSTRecord
= dyn_cast<const RecordType>(QT.getTypePtr())) {
@ -900,12 +911,14 @@ namespace utils {
if (isa<TypedefType>(SubTy)
|| isa<TemplateSpecializationType>(SubTy)
|| isa<ElaboratedType>(SubTy)
|| fullyQualify) {
|| fullyQualifyTmpltArg) {
mightHaveChanged = true;
desArgs.push_back(TemplateArgument(GetPartiallyDesugaredType(Ctx,
SubTy,
TypesToSkip,
fullyQualify)));
desArgs.push_back(TemplateArgument(
GetPartiallyDesugaredTypeImpl(Ctx,
SubTy,
TypesToSkip,
/*fullyQualifyType=*/true,
/*fullyQualifyTmpltArg=*/true)));
} else
desArgs.push_back(templateArgs[I]);
}
@ -931,6 +944,15 @@ namespace utils {
return QT;
}
QualType Transform::GetPartiallyDesugaredType(const ASTContext& Ctx,
QualType QT, const llvm::SmallSet<const Type*,4>& TypesToSkip,
bool fullyQualify/*=true*/)
{
return GetPartiallyDesugaredTypeImpl(Ctx,QT,TypesToSkip,
/*qualifyType*/fullyQualify,
/*qualifyTmpltArg*/fullyQualify);
}
NamespaceDecl* Lookup::Namespace(Sema* S, const char* Name,
const DeclContext* Within) {
DeclarationName DName = &S->Context.Idents.get(Name);

View File

@ -127,6 +127,7 @@ skip.insert(lookup.findType("string").getTypePtr());
skip.insert(lookup.findType("std::string").getTypePtr());
const clang::Type* t = 0;
const clang::TypedefType *td = 0;
clang::QualType QT;
using namespace cling::utils;
@ -281,6 +282,14 @@ QT = clang::QualType(t, 0);
Transform::GetPartiallyDesugaredType(Ctx, QT, skip).getAsString().c_str()
// CHECK: (const char *) "std::vector<Details::Impl>::iterator"
lookup.findScope("vector<Details::Impl>::const_iterator", &t);
QT = clang::QualType(t, 0);
td = QT->getAs<clang::TypedefType>();
clang::TypedefNameDecl *tdDecl = td->getDecl();
QT = Ctx.getTypedefType(tdDecl);
Transform::GetPartiallyDesugaredType(Ctx, QT, skip, true).getAsString().c_str()
// CHECK: (const char *) "std::vector<Details::Impl, std::allocator<Details::Impl> >::const_iterator"
const clang::Decl*decl=lookup.findScope("Embedded_objects",&t);
if (decl) {
const clang::CXXRecordDecl *cxxdecl