Add support for fully qualifying a template argument that is itself a template.
This is the case for example with gcc's __gnu_cxx::__common_pool_policy<__gnu_cxx::__pool,true> where __pool is actually a class template. Also reduce (a little bit) code duplication.
This commit is contained in:
parent
42da1a112a
commit
29746d4caf
@ -40,6 +40,15 @@ namespace utils {
|
||||
NestedNameSpecifier* scope,
|
||||
const Transform::Config& TypeConfig);
|
||||
|
||||
static NestedNameSpecifier*
|
||||
CreateNestedNameSpecifierForScopeOf(const ASTContext& Ctx,
|
||||
const Decl *decl,
|
||||
bool FullyQualified);
|
||||
|
||||
static
|
||||
NestedNameSpecifier* GetFullyQualifiedNameSpecifier(const ASTContext& Ctx,
|
||||
NestedNameSpecifier* scope);
|
||||
|
||||
bool Analyze::IsWrapper(const NamedDecl* ND) {
|
||||
if (!ND)
|
||||
return false;
|
||||
@ -174,6 +183,58 @@ namespace utils {
|
||||
return IntegerLiteral::Create(C, Addr, C.UnsignedLongTy, SourceLocation());
|
||||
}
|
||||
|
||||
static bool
|
||||
GetFullyQualifiedTemplateName(const ASTContext& Ctx, TemplateName &tname) {
|
||||
|
||||
bool changed = false;
|
||||
TemplateDecl *argtdecl = tname.getAsTemplateDecl();
|
||||
QualifiedTemplateName *qtname = tname.getAsQualifiedTemplateName();
|
||||
if (qtname && !qtname->hasTemplateKeyword()) {
|
||||
NestedNameSpecifier *NNS = qtname->getQualifier();
|
||||
NestedNameSpecifier *qNNS
|
||||
= GetFullyQualifiedNameSpecifier(Ctx,NNS);
|
||||
if (qNNS != NNS) {
|
||||
changed = true;
|
||||
NNS = qNNS;
|
||||
}
|
||||
} else {
|
||||
NestedNameSpecifier *NNS =
|
||||
CreateNestedNameSpecifierForScopeOf(Ctx, argtdecl, true);
|
||||
tname = Ctx.getQualifiedTemplateName(NNS,
|
||||
/*TemplateKeyword=*/ false,
|
||||
argtdecl);
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetFullyQualifiedTemplateArgument(const ASTContext& Ctx, TemplateArgument &arg)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
// Note: we do not handle TemplateArgument::Expression, to replace it
|
||||
// we need the information for the template instance decl.
|
||||
// See GetPartiallyDesugaredTypeImpl
|
||||
|
||||
if (arg.getKind() == TemplateArgument::Template) {
|
||||
TemplateName tname = arg.getAsTemplate();
|
||||
changed = GetFullyQualifiedTemplateName(Ctx, tname);
|
||||
if (changed) {
|
||||
arg = TemplateArgument(tname);
|
||||
}
|
||||
} else if (arg.getKind() == TemplateArgument::Type) {
|
||||
QualType SubTy = arg.getAsType();
|
||||
// Check if the type needs more desugaring and recurse.
|
||||
QualType QTFQ = TypeName::GetFullyQualifiedType(SubTy, Ctx);
|
||||
if (QTFQ != SubTy) {
|
||||
arg = TemplateArgument(QTFQ);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
static const Type*
|
||||
GetFullyQualifiedLocalType(const ASTContext& Ctx,
|
||||
const Type *typeptr) {
|
||||
@ -188,16 +249,12 @@ namespace utils {
|
||||
for (TemplateSpecializationType::iterator
|
||||
I = TST->begin(), E = TST->end();
|
||||
I != E; ++I) {
|
||||
if (I->getKind() != TemplateArgument::Type) {
|
||||
desArgs.push_back(*I);
|
||||
continue;
|
||||
}
|
||||
|
||||
QualType SubTy = I->getAsType();
|
||||
// Check if the type needs more desugaring and recurse.
|
||||
mightHaveChanged = true;
|
||||
QualType QTFQ = TypeName::GetFullyQualifiedType(SubTy, Ctx);
|
||||
desArgs.push_back(TemplateArgument(QTFQ));
|
||||
// cheap to copy and potentially modified by
|
||||
// GetFullyQualifedTemplateArgument
|
||||
TemplateArgument arg(*I);
|
||||
mightHaveChanged |= GetFullyQualifiedTemplateArgument(Ctx,arg);
|
||||
desArgs.push_back(arg);
|
||||
}
|
||||
|
||||
// If desugaring happened allocate new type in the AST.
|
||||
@ -224,17 +281,15 @@ namespace utils {
|
||||
llvm::SmallVector<TemplateArgument, 4> desArgs;
|
||||
for(unsigned int I = 0, E = templateArgs.size();
|
||||
I != E; ++I) {
|
||||
if (templateArgs[I].getKind() != TemplateArgument::Type) {
|
||||
desArgs.push_back(templateArgs[I]);
|
||||
continue;
|
||||
}
|
||||
|
||||
QualType SubTy = templateArgs[I].getAsType();
|
||||
// Check if the type needs more desugaring and recurse.
|
||||
mightHaveChanged = true;
|
||||
QualType QTFQ = TypeName::GetFullyQualifiedType(SubTy, Ctx);
|
||||
desArgs.push_back(TemplateArgument(QTFQ));
|
||||
// cheap to copy and potentially modified by
|
||||
// GetFullyQualifedTemplateArgument
|
||||
TemplateArgument arg(templateArgs[I]);
|
||||
mightHaveChanged |= GetFullyQualifiedTemplateArgument(Ctx,arg);
|
||||
desArgs.push_back(arg);
|
||||
|
||||
}
|
||||
|
||||
// If desugaring happened allocate new type in the AST.
|
||||
if (mightHaveChanged) {
|
||||
TemplateName TN(TSTdecl->getSpecializedTemplate());
|
||||
@ -1083,27 +1138,39 @@ namespace utils {
|
||||
for(TemplateSpecializationType::iterator I = TST->begin(), E = TST->end();
|
||||
I != E; ++I, ++argi) {
|
||||
|
||||
if (I->getKind() == TemplateArgument::Expression) {
|
||||
// If we have an expression, we need to replace it / desugar it
|
||||
// as it could contain unqualifed (or partially qualified or
|
||||
// private) parts.
|
||||
if (I->getKind() == TemplateArgument::Expression) {
|
||||
// If we have an expression, we need to replace it / desugar it
|
||||
// as it could contain unqualifed (or partially qualified or
|
||||
// private) parts.
|
||||
|
||||
QualType canon = QT->getCanonicalTypeInternal();
|
||||
const RecordType *TSTRecord
|
||||
= dyn_cast<const RecordType>(canon.getTypePtr());
|
||||
if (TSTRecord) {
|
||||
if (const ClassTemplateSpecializationDecl* TSTdecl =
|
||||
dyn_cast<ClassTemplateSpecializationDecl>(TSTRecord->getDecl()))
|
||||
{
|
||||
const TemplateArgumentList& templateArgs
|
||||
= TSTdecl->getTemplateArgs();
|
||||
QualType canon = QT->getCanonicalTypeInternal();
|
||||
const RecordType *TSTRecord
|
||||
= dyn_cast<const RecordType>(canon.getTypePtr());
|
||||
if (TSTRecord) {
|
||||
if (const ClassTemplateSpecializationDecl* TSTdecl =
|
||||
dyn_cast<ClassTemplateSpecializationDecl>(TSTRecord->getDecl()))
|
||||
{
|
||||
const TemplateArgumentList& templateArgs
|
||||
= TSTdecl->getTemplateArgs();
|
||||
|
||||
mightHaveChanged = true;
|
||||
desArgs.push_back(templateArgs[argi]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
mightHaveChanged = true;
|
||||
desArgs.push_back(templateArgs[argi]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (I->getKind() == TemplateArgument::Template) {
|
||||
TemplateName tname = I->getAsTemplate();
|
||||
// Note: should we not also desugar?
|
||||
bool changed = GetFullyQualifiedTemplateName(Ctx, tname);
|
||||
if (changed) {
|
||||
desArgs.push_back(TemplateArgument(tname));
|
||||
mightHaveChanged = true;
|
||||
} else
|
||||
desArgs.push_back(*I);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (I->getKind() != TemplateArgument::Type) {
|
||||
desArgs.push_back(*I);
|
||||
@ -1155,6 +1222,28 @@ namespace utils {
|
||||
for(unsigned int I = 0, E = templateArgs.size();
|
||||
I != E; ++I) {
|
||||
|
||||
#if 0
|
||||
// This alternative code is not quite right as it would
|
||||
// not call GetPartiallyDesugaredTypeImpl on Types.
|
||||
|
||||
// cheap to copy and potentially modified by
|
||||
// GetFullyQualifedTemplateArgument
|
||||
TemplateArgument arg(*I);
|
||||
mightHaveChanged | = GetFullyQualifiedTemplateArgument(Ctx,arg);
|
||||
desArgs.push_back(arg);
|
||||
#endif
|
||||
if (templateArgs[I].getKind() == TemplateArgument::Template) {
|
||||
TemplateName tname = templateArgs[I].getAsTemplate();
|
||||
// Note: should we not also desugar?
|
||||
bool changed = GetFullyQualifiedTemplateName(Ctx, tname);
|
||||
if (changed) {
|
||||
desArgs.push_back(TemplateArgument(tname));
|
||||
mightHaveChanged = true;
|
||||
} else
|
||||
desArgs.push_back(templateArgs[I]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (templateArgs[I].getKind() != TemplateArgument::Type) {
|
||||
desArgs.push_back(templateArgs[I]);
|
||||
continue;
|
||||
@ -1278,35 +1367,20 @@ namespace utils {
|
||||
|
||||
static NestedNameSpecifier*
|
||||
CreateNestedNameSpecifierForScopeOf(const ASTContext& Ctx,
|
||||
const Type *TypePtr,
|
||||
const Decl *decl,
|
||||
bool FullyQualified)
|
||||
{
|
||||
// Create a nested name specifier for the declaring context of the type.
|
||||
|
||||
if (!TypePtr)
|
||||
return 0;
|
||||
assert(decl);
|
||||
|
||||
Decl *decl = 0;
|
||||
if (const TypedefType* typedeftype = llvm::dyn_cast<TypedefType>(TypePtr)) {
|
||||
decl = typedeftype->getDecl();
|
||||
} else {
|
||||
// There are probably other cases ...
|
||||
if (const TagType* tagdecltype = llvm::dyn_cast_or_null<TagType>(TypePtr))
|
||||
decl = tagdecltype->getDecl();
|
||||
else
|
||||
decl = TypePtr->getAsCXXRecordDecl();
|
||||
}
|
||||
|
||||
if (!decl)
|
||||
return 0;
|
||||
|
||||
NamedDecl* outer
|
||||
const NamedDecl* outer
|
||||
= llvm::dyn_cast_or_null<NamedDecl>(decl->getDeclContext());
|
||||
NamespaceDecl* outer_ns
|
||||
const NamespaceDecl* outer_ns
|
||||
= llvm::dyn_cast_or_null<NamespaceDecl>(decl->getDeclContext());
|
||||
if (outer && !(outer_ns && outer_ns->isAnonymousNamespace())) {
|
||||
|
||||
if (CXXRecordDecl *cxxdecl
|
||||
if (const CXXRecordDecl *cxxdecl
|
||||
= llvm::dyn_cast<CXXRecordDecl>(decl->getDeclContext())) {
|
||||
|
||||
if (ClassTemplateDecl *clTempl = cxxdecl->getDescribedClassTemplate()) {
|
||||
@ -1335,6 +1409,33 @@ namespace utils {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static NestedNameSpecifier*
|
||||
CreateNestedNameSpecifierForScopeOf(const ASTContext& Ctx,
|
||||
const Type *TypePtr,
|
||||
bool FullyQualified)
|
||||
{
|
||||
// Create a nested name specifier for the declaring context of the type.
|
||||
|
||||
if (!TypePtr)
|
||||
return 0;
|
||||
|
||||
Decl *decl = 0;
|
||||
if (const TypedefType* typedeftype = llvm::dyn_cast<TypedefType>(TypePtr)) {
|
||||
decl = typedeftype->getDecl();
|
||||
} else {
|
||||
// There are probably other cases ...
|
||||
if (const TagType* tagdecltype = llvm::dyn_cast_or_null<TagType>(TypePtr))
|
||||
decl = tagdecltype->getDecl();
|
||||
else
|
||||
decl = TypePtr->getAsCXXRecordDecl();
|
||||
}
|
||||
|
||||
if (!decl)
|
||||
return 0;
|
||||
|
||||
return CreateNestedNameSpecifierForScopeOf(Ctx, decl, FullyQualified);
|
||||
}
|
||||
|
||||
NestedNameSpecifier*
|
||||
TypeName::CreateNestedNameSpecifier(const ASTContext& Ctx,
|
||||
const NamespaceDecl* Namesp) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user