2012-09-05 13:37:39 +04:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author: Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//------------------------------------------------------------------------------
# include "cling/Utils/AST.h"
# include "clang/AST/ASTContext.h"
# include "clang/AST/DeclarationName.h"
# include "clang/Sema/Sema.h"
# include "clang/Sema/Lookup.h"
2013-02-08 02:56:10 +04:00
# include "clang/AST/DeclTemplate.h"
2012-09-05 13:37:39 +04:00
2012-10-15 20:57:53 +04:00
# include "llvm/ADT/ArrayRef.h"
2012-10-17 12:52:24 +04:00
# include "llvm/ADT/StringRef.h"
2013-02-14 21:23:47 +04:00
# include <stdio.h>
2012-09-05 13:37:39 +04:00
using namespace clang ;
namespace cling {
namespace utils {
2012-10-15 20:57:53 +04:00
2013-08-29 02:02:57 +04:00
static
QualType GetPartiallyDesugaredTypeImpl ( const ASTContext & Ctx ,
QualType QT ,
2013-09-03 08:44:24 +04:00
const Transform : : Config & TypeConfig ,
2013-08-29 02:02:57 +04:00
bool fullyQualifyType ,
bool fullyQualifyTmpltArg ) ;
static
NestedNameSpecifier * GetPartiallyDesugaredNNS ( const ASTContext & Ctx ,
NestedNameSpecifier * scope ,
2013-09-03 08:44:24 +04:00
const Transform : : Config & TypeConfig ) ;
2013-08-29 02:02:57 +04:00
2012-10-17 12:52:24 +04:00
bool Analyze : : IsWrapper ( const NamedDecl * ND ) {
if ( ! ND )
return false ;
2013-03-01 22:12:48 +04:00
return StringRef ( ND - > getNameAsString ( ) )
2012-10-17 12:52:24 +04:00
. startswith ( Synthesize : : UniquePrefix ) ;
}
2013-08-28 02:25:37 +04:00
bool Analyze : : IsCFWrapper ( const NamedDecl * ND ) {
if ( ! ND ) {
return false ;
}
bool ret = StringRef ( ND - > getNameAsString ( ) ) . startswith (
Synthesize : : CFUniquePrefix ) ;
return ret ;
}
2012-10-19 15:56:52 +04:00
Expr * Analyze : : GetOrCreateLastExpr ( FunctionDecl * FD ,
2012-10-19 13:22:36 +04:00
int * FoundAt /*=0*/ ,
bool omitDeclStmts /*=true*/ ,
2012-10-19 15:56:52 +04:00
Sema * S /*=0*/ ) {
2012-10-19 13:22:36 +04:00
assert ( FD & & " We need a function declaration! " ) ;
assert ( ( omitDeclStmts | | S )
& & " Sema needs to be set when omitDeclStmts is false " ) ;
2012-10-15 20:57:53 +04:00
if ( FoundAt )
* FoundAt = - 1 ;
2012-10-19 13:22:36 +04:00
Expr * result = 0 ;
2012-10-15 20:57:53 +04:00
if ( CompoundStmt * CS = dyn_cast < CompoundStmt > ( FD - > getBody ( ) ) ) {
2013-03-01 22:12:48 +04:00
ArrayRef < Stmt * > Stmts
2012-10-15 20:57:53 +04:00
= llvm : : makeArrayRef ( CS - > body_begin ( ) , CS - > size ( ) ) ;
int indexOfLastExpr = Stmts . size ( ) ;
2012-10-19 13:22:36 +04:00
while ( indexOfLastExpr - - ) {
if ( ! isa < NullStmt > ( Stmts [ indexOfLastExpr ] ) )
break ;
}
2012-10-15 20:57:53 +04:00
if ( FoundAt )
* FoundAt = indexOfLastExpr ;
2012-10-19 13:22:36 +04:00
2012-10-15 20:57:53 +04:00
if ( indexOfLastExpr < 0 )
return 0 ;
2012-10-19 13:22:36 +04:00
if ( ( result = dyn_cast < Expr > ( Stmts [ indexOfLastExpr ] ) ) )
return result ;
if ( ! omitDeclStmts )
if ( DeclStmt * DS = dyn_cast < DeclStmt > ( Stmts [ indexOfLastExpr ] ) ) {
std : : vector < Stmt * > newBody = Stmts . vec ( ) ;
for ( DeclStmt : : reverse_decl_iterator I = DS - > decl_rbegin ( ) ,
E = DS - > decl_rend ( ) ; I ! = E ; + + I ) {
if ( VarDecl * VD = dyn_cast < VarDecl > ( * I ) ) {
// Change the void function's return type
// We can't PushDeclContext, because we don't have scope.
Sema : : ContextRAII pushedDC ( * S , FD ) ;
QualType VDTy = VD - > getType ( ) . getNonReferenceType ( ) ;
// Get the location of the place we will insert.
SourceLocation Loc
= newBody [ indexOfLastExpr ] - > getLocEnd ( ) . getLocWithOffset ( 1 ) ;
Expr * DRE = S - > BuildDeclRefExpr ( VD , VDTy , VK_LValue , Loc ) . take ( ) ;
assert ( DRE & & " Cannot be null " ) ;
indexOfLastExpr + + ;
newBody . insert ( newBody . begin ( ) + indexOfLastExpr , DRE ) ;
// Attach the new body (note: it does dealloc/alloc of all nodes)
2012-10-22 16:35:32 +04:00
CS - > setStmts ( S - > getASTContext ( ) , & newBody . front ( ) , newBody . size ( ) ) ;
2012-10-19 13:22:36 +04:00
if ( FoundAt )
* FoundAt = indexOfLastExpr ;
return DRE ;
}
}
}
return result ;
2012-10-15 20:57:53 +04:00
}
2012-10-19 13:22:36 +04:00
return result ;
2012-10-15 20:57:53 +04:00
}
2012-10-19 17:49:34 +04:00
const char * const Synthesize : : UniquePrefix = " __cling_Un1Qu3 " ;
2013-08-28 02:25:37 +04:00
const char * const Synthesize : : CFUniquePrefix = " __cf_Un1Qu3 " ;
2012-10-17 12:52:24 +04:00
2012-09-05 13:37:39 +04:00
Expr * Synthesize : : CStyleCastPtrExpr ( Sema * S , QualType Ty , uint64_t Ptr ) {
2013-04-25 16:48:15 +04:00
ASTContext & Ctx = S - > getASTContext ( ) ;
return CStyleCastPtrExpr ( S , Ty , Synthesize : : IntegerLiteralExpr ( Ctx , Ptr ) ) ;
}
Expr * Synthesize : : CStyleCastPtrExpr ( Sema * S , QualType Ty , Expr * E ) {
2012-09-05 13:37:39 +04:00
ASTContext & Ctx = S - > getASTContext ( ) ;
if ( ! Ty - > isPointerType ( ) )
Ty = Ctx . getPointerType ( Ty ) ;
2013-04-25 16:48:15 +04:00
TypeSourceInfo * TSI = Ctx . getTrivialTypeSourceInfo ( Ty , SourceLocation ( ) ) ;
Expr * Result
= S - > BuildCStyleCastExpr ( SourceLocation ( ) , TSI , SourceLocation ( ) , E ) . take ( ) ;
2012-09-05 13:37:39 +04:00
assert ( Result & & " Cannot create CStyleCastPtrExpr " ) ;
return Result ;
}
2012-11-21 21:05:10 +04:00
IntegerLiteral * Synthesize : : IntegerLiteralExpr ( ASTContext & C , uint64_t Ptr ) {
const llvm : : APInt Addr ( 8 * sizeof ( void * ) , Ptr ) ;
return IntegerLiteral : : Create ( C , Addr , C . UnsignedLongTy , SourceLocation ( ) ) ;
}
2012-12-11 12:26:00 +04:00
static
NestedNameSpecifier * CreateNestedNameSpecifier ( const ASTContext & Ctx ,
2013-03-01 21:59:59 +04:00
const NamespaceDecl * cl ) {
2012-12-11 12:26:00 +04:00
2013-03-01 21:59:59 +04:00
const NamespaceDecl * outer
= dyn_cast_or_null < NamespaceDecl > ( cl - > getDeclContext ( ) ) ;
2012-12-11 12:26:00 +04:00
if ( outer & & outer - > getName ( ) . size ( ) ) {
NestedNameSpecifier * outerNNS = CreateNestedNameSpecifier ( Ctx , outer ) ;
return NestedNameSpecifier : : Create ( Ctx , outerNNS ,
2013-03-01 21:59:59 +04:00
// Newer version of clang do not require this const_cast
const_cast < NamespaceDecl * > ( cl ) ) ;
2012-12-11 12:26:00 +04:00
} else {
return NestedNameSpecifier : : Create ( Ctx ,
0 , /* no starting '::'*/
2013-03-01 21:59:59 +04:00
// Newer version of clang do not require this const_cast
const_cast < NamespaceDecl * > ( cl ) ) ;
2012-12-11 12:26:00 +04:00
}
}
static
NestedNameSpecifier * CreateNestedNameSpecifier ( const ASTContext & Ctx ,
2013-03-01 21:59:59 +04:00
const TagDecl * cl ) {
2012-12-11 12:26:00 +04:00
2013-03-01 21:59:59 +04:00
const NamedDecl * outer = dyn_cast_or_null < NamedDecl > ( cl - > getDeclContext ( ) ) ;
2012-12-11 12:26:00 +04:00
if ( outer & & outer - > getName ( ) . size ( ) ) {
NestedNameSpecifier * outerNNS ;
if ( cl - > getDeclContext ( ) - > isNamespace ( ) ) {
outerNNS = CreateNestedNameSpecifier ( Ctx ,
2013-03-01 21:59:59 +04:00
dyn_cast < NamespaceDecl > ( outer ) ) ;
2012-12-11 12:26:00 +04:00
} else {
outerNNS = CreateNestedNameSpecifier ( Ctx ,
2013-03-01 21:59:59 +04:00
dyn_cast < TagDecl > ( outer ) ) ;
2012-12-11 12:26:00 +04:00
}
return NestedNameSpecifier : : Create ( Ctx , outerNNS ,
false /* template keyword wanted */ ,
Ctx . getTypeDeclType ( cl ) . getTypePtr ( ) ) ;
} else {
return NestedNameSpecifier : : Create ( Ctx ,
0 , /* no starting '::'*/
false /* template keyword wanted */ ,
Ctx . getTypeDeclType ( cl ) . getTypePtr ( ) ) ;
}
}
2013-03-01 21:59:59 +04:00
static
NestedNameSpecifier * GetFullyQualifiedNameSpecifier ( const ASTContext & Ctx ,
NestedNameSpecifier * scope ) {
// Return a fully qualified version of this name specifier
NestedNameSpecifier * outer_nns = scope ;
while ( outer_nns - > getPrefix ( )
& & outer_nns - > getKind ( ) ! = NestedNameSpecifier : : Global ) {
outer_nns = outer_nns - > getPrefix ( ) ;
}
Decl * decl = 0 ;
if ( outer_nns - > getKind ( ) = = NestedNameSpecifier : : Global ) {
// leave decl to 0.
2013-03-01 22:06:58 +04:00
} else if ( const Type * type = outer_nns - > getAsType ( ) ) {
2013-03-01 21:59:59 +04:00
// Find decl context.
const TypedefType * typedeftype = dyn_cast_or_null < TypedefType > ( type ) ;
if ( typedeftype ) {
decl = typedeftype - > getDecl ( ) ;
} else {
// There are probably other cases ...
const TagType * tagdecltype = dyn_cast_or_null < TagType > ( type ) ;
if ( tagdecltype ) {
decl = tagdecltype - > getDecl ( ) ;
} else {
decl = type - > getAsCXXRecordDecl ( ) ;
}
}
} else if ( ( decl = outer_nns - > getAsNamespace ( ) ) ) {
// Found decl.
} else if ( ( decl = outer_nns - > getAsNamespaceAlias ( ) ) ) {
// Found decl.
}
bool needCreate = false ;
if ( decl = = 0 ) {
// We have the global namespace in there, we don't want it.
needCreate = true ;
} else {
NamedDecl * outer = dyn_cast < NamedDecl > ( decl - > getDeclContext ( ) ) ;
NamespaceDecl * outer_ns = dyn_cast < NamespaceDecl > ( decl - > getDeclContext ( ) ) ;
if ( outer
& & ! ( outer_ns & & outer_ns - > isAnonymousNamespace ( ) )
& & outer - > getName ( ) . size ( ) )
{
needCreate = true ;
}
}
if ( needCreate ) {
if ( NamespaceDecl * ns = scope - > getAsNamespace ( ) ) {
return CreateNestedNameSpecifier ( Ctx , ns ) ;
} else if ( NamespaceAliasDecl * alias = scope - > getAsNamespaceAlias ( ) )
{
return CreateNestedNameSpecifier ( Ctx ,
alias - > getNamespace ( ) - > getCanonicalDecl ( ) ) ;
} else {
// We should only create the nested name specifier
// if the outer scope is really a TagDecl.
// It could also be a CXXMethod for example.
2013-03-01 22:06:58 +04:00
const Type * type = scope - > getAsType ( ) ;
2013-03-01 21:59:59 +04:00
const TypedefType * typedeftype = dyn_cast_or_null < TypedefType > ( type ) ;
Decl * idecl ;
if ( typedeftype ) {
idecl = typedeftype - > getDecl ( ) ;
} else {
// There are probably other cases ...
const TagType * tagdecltype = dyn_cast_or_null < TagType > ( type ) ;
if ( tagdecltype ) {
idecl = tagdecltype - > getDecl ( ) ;
} else {
idecl = type - > getAsCXXRecordDecl ( ) ;
}
}
2013-03-01 22:12:48 +04:00
TagDecl * tdecl = dyn_cast < TagDecl > ( idecl ) ;
2013-03-01 21:59:59 +04:00
if ( tdecl ) {
return CreateNestedNameSpecifier ( Ctx , tdecl ) ;
}
}
}
// It was fine.
return scope ;
}
static
NestedNameSpecifier * SelectPrefix ( const ASTContext & Ctx ,
2013-03-01 22:06:58 +04:00
const DeclContext * declContext ,
2013-03-01 21:59:59 +04:00
NestedNameSpecifier * original_prefix ,
2013-09-03 08:44:24 +04:00
const Transform : : Config & TypeConfig ) {
2013-03-01 21:59:59 +04:00
// We have to also desugar the prefix.
NestedNameSpecifier * prefix = 0 ;
if ( declContext ) {
// We had a scope prefix as input, let see if it is still
// the same as the scope of the result and if it is, then
// we use it.
if ( declContext - > isNamespace ( ) ) {
// Deal with namespace. This is mostly about dealing with
// namespace aliases (i.e. keeping the one the user used).
2013-03-01 22:12:48 +04:00
const NamespaceDecl * new_ns = dyn_cast < NamespaceDecl > ( declContext ) ;
2013-03-01 21:59:59 +04:00
if ( new_ns ) {
new_ns = new_ns - > getCanonicalDecl ( ) ;
NamespaceDecl * old_ns = 0 ;
if ( original_prefix ) {
original_prefix - > getAsNamespace ( ) ;
if ( old_ns ) {
old_ns = old_ns - > getCanonicalDecl ( ) ;
}
else if ( NamespaceAliasDecl * alias =
original_prefix - > getAsNamespaceAlias ( ) )
{
old_ns = alias - > getNamespace ( ) - > getCanonicalDecl ( ) ;
}
}
if ( old_ns = = new_ns ) {
// This is the same namespace, use the original prefix
// as a starting point.
prefix = GetFullyQualifiedNameSpecifier ( Ctx , original_prefix ) ;
} else {
prefix = CreateNestedNameSpecifier ( Ctx ,
dyn_cast < NamespaceDecl > ( new_ns ) ) ;
}
}
} else {
2013-03-01 22:12:48 +04:00
const CXXRecordDecl * newtype = dyn_cast < CXXRecordDecl > ( declContext ) ;
2013-03-01 21:59:59 +04:00
if ( newtype & & original_prefix ) {
// Deal with a class
2013-03-01 22:06:58 +04:00
const Type * oldtype = original_prefix - > getAsType ( ) ;
2013-03-01 21:59:59 +04:00
if ( oldtype & &
// NOTE: Should we compare the RecordDecl instead?
oldtype - > getAsCXXRecordDecl ( ) = = newtype )
{
// This is the same type, use the original prefix as a starting
// point.
2013-09-03 08:44:24 +04:00
prefix = GetPartiallyDesugaredNNS ( Ctx , original_prefix , TypeConfig ) ;
2013-03-01 21:59:59 +04:00
} else {
2013-03-01 22:12:48 +04:00
const TagDecl * tdecl = dyn_cast < TagDecl > ( declContext ) ;
2013-03-01 21:59:59 +04:00
if ( tdecl ) {
prefix = CreateNestedNameSpecifier ( Ctx , tdecl ) ;
}
}
} else {
// We should only create the nested name specifier
// if the outer scope is really a TagDecl.
// It could also be a CXXMethod for example.
2013-03-01 22:12:48 +04:00
const TagDecl * tdecl = dyn_cast < TagDecl > ( declContext ) ;
2013-03-01 21:59:59 +04:00
if ( tdecl ) {
prefix = CreateNestedNameSpecifier ( Ctx , tdecl ) ;
}
}
}
} else {
prefix = GetFullyQualifiedNameSpecifier ( Ctx , original_prefix ) ;
}
return prefix ;
}
static
2012-12-11 12:26:00 +04:00
NestedNameSpecifier * SelectPrefix ( const ASTContext & Ctx ,
const ElaboratedType * etype ,
NestedNameSpecifier * original_prefix ,
2013-09-03 08:44:24 +04:00
const Transform : : Config & TypeConfig ) {
2012-12-11 12:26:00 +04:00
// We have to also desugar the prefix.
NestedNameSpecifier * prefix = etype - > getQualifier ( ) ;
2013-02-15 16:42:09 +04:00
if ( original_prefix & & prefix ) {
2012-12-11 12:26:00 +04:00
// We had a scope prefix as input, let see if it is still
// the same as the scope of the result and if it is, then
// we use it.
2013-03-01 22:06:58 +04:00
const Type * newtype = prefix - > getAsType ( ) ;
2012-12-11 12:26:00 +04:00
if ( newtype ) {
// Deal with a class
2013-03-01 22:06:58 +04:00
const Type * oldtype = original_prefix - > getAsType ( ) ;
2012-12-11 12:26:00 +04:00
if ( oldtype & &
// NOTE: Should we compare the RecordDecl instead?
oldtype - > getAsCXXRecordDecl ( ) = = newtype - > getAsCXXRecordDecl ( ) )
{
// This is the same type, use the original prefix as a starting
// point.
2013-09-03 08:44:24 +04:00
prefix = GetPartiallyDesugaredNNS ( Ctx , original_prefix , TypeConfig ) ;
2012-12-11 12:26:00 +04:00
} else {
2013-09-03 08:44:24 +04:00
prefix = GetPartiallyDesugaredNNS ( Ctx , prefix , TypeConfig ) ;
2012-12-11 12:26:00 +04:00
}
} else {
// Deal with namespace. This is mostly about dealing with
// namespace aliases (i.e. keeping the one the user used).
const NamespaceDecl * new_ns = prefix - > getAsNamespace ( ) ;
if ( new_ns ) {
new_ns = new_ns - > getCanonicalDecl ( ) ;
}
2013-02-15 16:42:09 +04:00
else if ( NamespaceAliasDecl * alias = prefix - > getAsNamespaceAlias ( ) )
2012-12-11 12:26:00 +04:00
{
new_ns = alias - > getNamespace ( ) - > getCanonicalDecl ( ) ;
}
if ( new_ns ) {
const NamespaceDecl * old_ns = original_prefix - > getAsNamespace ( ) ;
if ( old_ns ) {
old_ns = old_ns - > getCanonicalDecl ( ) ;
}
else if ( NamespaceAliasDecl * alias =
original_prefix - > getAsNamespaceAlias ( ) )
{
old_ns = alias - > getNamespace ( ) - > getCanonicalDecl ( ) ;
}
if ( old_ns = = new_ns ) {
// This is the same namespace, use the original prefix
// as a starting point.
2013-03-01 21:59:59 +04:00
prefix = GetFullyQualifiedNameSpecifier ( Ctx , original_prefix ) ;
} else {
prefix = GetFullyQualifiedNameSpecifier ( Ctx , prefix ) ;
2012-12-11 12:26:00 +04:00
}
2013-03-01 21:59:59 +04:00
} else {
prefix = GetFullyQualifiedNameSpecifier ( Ctx , prefix ) ;
2012-12-11 12:26:00 +04:00
}
}
}
return prefix ;
}
2013-03-01 21:59:59 +04:00
2012-09-05 13:37:39 +04:00
static
2013-09-03 08:44:24 +04:00
NestedNameSpecifier * GetPartiallyDesugaredNNS ( const ASTContext & Ctx ,
2012-09-05 13:37:39 +04:00
NestedNameSpecifier * scope ,
2013-09-03 08:44:24 +04:00
const Transform : : Config & TypeConfig ) {
2012-09-05 13:37:39 +04:00
// Desugar the scope qualifier if needed.
2013-03-01 21:59:59 +04:00
if ( const Type * scope_type = scope - > getAsType ( ) ) {
2012-09-05 13:37:39 +04:00
// this is not a namespace, so we might need to desugar
2013-08-29 02:02:57 +04:00
QualType desugared = GetPartiallyDesugaredTypeImpl ( Ctx ,
QualType ( scope_type , 0 ) ,
2013-09-03 08:44:24 +04:00
TypeConfig ,
2013-08-29 02:02:57 +04:00
/*qualifyType=*/ false ,
/*qualifyTmpltArg=*/ true ) ;
2013-03-01 21:59:59 +04:00
2012-09-05 13:37:39 +04:00
NestedNameSpecifier * outer_scope = scope - > getPrefix ( ) ;
2013-03-01 21:59:59 +04:00
const ElaboratedType * etype
2013-03-01 22:12:48 +04:00
= dyn_cast < ElaboratedType > ( desugared . getTypePtr ( ) ) ;
2013-03-01 21:59:59 +04:00
if ( etype ) {
// The desugarding returned an elaborated type even-though we
// did not request it (/*fullyQualify=*/false), so we must have been
// looking a typedef pointing at a (or another) scope.
if ( outer_scope ) {
2013-09-03 08:44:24 +04:00
outer_scope = SelectPrefix ( Ctx , etype , outer_scope , TypeConfig ) ;
2013-03-01 21:59:59 +04:00
} else {
outer_scope = GetPartiallyDesugaredNNS ( Ctx , etype - > getQualifier ( ) ,
2013-09-03 08:44:24 +04:00
TypeConfig ) ;
2013-03-01 21:59:59 +04:00
}
desugared = etype - > getNamedType ( ) ;
2012-12-11 12:26:00 +04:00
} else {
2013-03-01 21:59:59 +04:00
Decl * decl = 0 ;
const TypedefType * typedeftype =
2013-03-01 22:12:48 +04:00
dyn_cast_or_null < TypedefType > ( & ( * desugared ) ) ;
2012-12-11 12:26:00 +04:00
if ( typedeftype ) {
decl = typedeftype - > getDecl ( ) ;
} else {
// There are probably other cases ...
2013-03-01 21:59:59 +04:00
const TagType * tagdecltype = dyn_cast_or_null < TagType > ( & ( * desugared ) ) ;
2012-12-11 12:26:00 +04:00
if ( tagdecltype ) {
decl = tagdecltype - > getDecl ( ) ;
} else {
2013-03-01 21:59:59 +04:00
decl = desugared - > getAsCXXRecordDecl ( ) ;
2012-12-11 12:26:00 +04:00
}
}
if ( decl ) {
2013-03-01 21:59:59 +04:00
NamedDecl * outer
= dyn_cast_or_null < NamedDecl > ( decl - > getDeclContext ( ) ) ;
2012-12-11 12:26:00 +04:00
NamespaceDecl * outer_ns
2013-03-01 21:59:59 +04:00
= dyn_cast_or_null < NamespaceDecl > ( decl - > getDeclContext ( ) ) ;
2012-12-11 12:26:00 +04:00
if ( outer
& & ! ( outer_ns & & outer_ns - > isAnonymousNamespace ( ) )
& & outer - > getName ( ) . size ( ) ) {
2013-03-01 21:59:59 +04:00
outer_scope = SelectPrefix ( Ctx , decl - > getDeclContext ( ) ,
2013-09-03 08:44:24 +04:00
outer_scope , TypeConfig ) ;
2013-03-01 21:59:59 +04:00
} else {
outer_scope = 0 ;
2012-12-11 12:26:00 +04:00
}
2013-03-01 21:59:59 +04:00
} else if ( outer_scope ) {
2013-09-03 08:44:24 +04:00
outer_scope = GetPartiallyDesugaredNNS ( Ctx , outer_scope , TypeConfig ) ;
2013-03-01 21:59:59 +04:00
}
2012-09-05 13:37:39 +04:00
}
return NestedNameSpecifier : : Create ( Ctx , outer_scope ,
false /* template keyword wanted */ ,
desugared . getTypePtr ( ) ) ;
2013-03-01 21:59:59 +04:00
} else {
return GetFullyQualifiedNameSpecifier ( Ctx , scope ) ;
2012-09-05 13:37:39 +04:00
}
}
2013-02-14 21:23:47 +04:00
static bool IsStdDetails ( const TagType * tagTy )
{
// Return true if the TagType is a 'details' of the std implementation.
// (For now it means declared in std and __gnu_cxx
const TagDecl * decl = tagTy - > getDecl ( ) ;
assert ( decl ) ;
const NamedDecl * outer = dyn_cast_or_null < NamedDecl > ( decl - > getDeclContext ( ) ) ;
while ( outer & & outer - > getName ( ) . size ( ) ) {
2013-08-30 14:46:44 +04:00
if ( //outer->getName().compare("std") == 0 ||
2013-02-14 21:23:47 +04:00
outer - > getName ( ) . compare ( " __gnu_cxx " ) = = 0 ) {
return true ;
}
outer = dyn_cast_or_null < NamedDecl > ( outer - > getDeclContext ( ) ) ;
}
return false ;
}
static bool ShouldKeepTypedef ( QualType QT ,
2012-09-23 01:30:24 +04:00
const llvm : : SmallSet < const Type * , 4 > & TypesToSkip )
{
// Return true, if we should keep this typedef rather than desugaring it.
2013-09-03 08:44:24 +04:00
if ( 0 ! = TypesToSkip . count ( QT . getTypePtr ( ) ) )
2012-09-23 01:30:24 +04:00
return true ;
const TypedefType * typedeftype =
2013-03-01 22:12:48 +04:00
dyn_cast_or_null < TypedefType > ( QT . getTypePtr ( ) ) ;
2012-09-23 01:30:24 +04:00
const TypedefNameDecl * decl = typedeftype ? typedeftype - > getDecl ( ) : 0 ;
if ( decl ) {
2013-01-04 21:26:48 +04:00
const NamedDecl * outer
2013-03-01 22:12:48 +04:00
= dyn_cast_or_null < NamedDecl > ( decl - > getDeclContext ( ) ) ;
2013-02-14 21:23:47 +04:00
// We want to keep the typedef that are defined within std and
// are pointing to something also declared in std (usually an
// implementation details like std::basic_string or __gnu_cxx::iterator.
while ( outer & & outer - > getName ( ) . size ( ) ) {
// NOTE: Net is being cast too widely, replace by a lookup.
// or by using Sema::getStdNamespace
if ( outer - > getName ( ) . compare ( " std " ) = = 0 ) {
// And now let's check that the target is also within std.
2013-03-01 05:33:38 +04:00
const Type * underlyingType = decl - > getUnderlyingType ( ) . getSplitDesugaredType ( ) . Ty ;
2013-02-14 21:23:47 +04:00
const ElaboratedType * elTy = dyn_cast < ElaboratedType > ( underlyingType ) ;
if ( elTy ) {
underlyingType = elTy - > getNamedType ( ) . getTypePtr ( ) ;
}
const TagType * tagTy = underlyingType - > getAs < TagType > ( ) ;
if ( tagTy ) {
bool details = IsStdDetails ( tagTy ) ;
if ( details ) return true ;
2013-01-04 21:26:48 +04:00
}
}
2013-02-14 21:23:47 +04:00
outer = dyn_cast_or_null < NamedDecl > ( outer - > getDeclContext ( ) ) ;
2012-09-23 01:30:24 +04:00
}
}
return false ;
}
2012-12-02 00:37:09 +04:00
bool SingleStepPartiallyDesugarTypeImpl ( QualType & QT )
2012-11-30 01:40:44 +04:00
{
// WARNING:
//
// The large blocks of commented-out code in this routine
// are there to support doing more desugaring in the future,
// we will probably have to.
//
// Do not delete until we are completely sure we will
// not be changing this routine again!
//
const Type * QTy = QT . getTypePtr ( ) ;
Type : : TypeClass TC = QTy - > getTypeClass ( ) ;
switch ( TC ) {
//
// Unconditionally sugared types.
//
case Type : : Paren : {
return false ;
//const ParenType* Ty = llvm::cast<ParenType>(QTy);
//QT = Ty->desugar();
//return true;
}
case Type : : Typedef : {
const TypedefType * Ty = llvm : : cast < TypedefType > ( QTy ) ;
QT = Ty - > desugar ( ) ;
return true ;
}
case Type : : TypeOf : {
const TypeOfType * Ty = llvm : : cast < TypeOfType > ( QTy ) ;
QT = Ty - > desugar ( ) ;
return true ;
}
case Type : : Attributed : {
return false ;
//const AttributedType* Ty = llvm::cast<AttributedType>(QTy);
//QT = Ty->desugar();
//return true;
}
case Type : : SubstTemplateTypeParm : {
2013-02-08 02:56:10 +04:00
const SubstTemplateTypeParmType * Ty =
llvm : : cast < SubstTemplateTypeParmType > ( QTy ) ;
QT = Ty - > desugar ( ) ;
return true ;
2012-11-30 01:40:44 +04:00
}
case Type : : Elaborated : {
2013-03-01 05:33:38 +04:00
const ElaboratedType * Ty = llvm : : cast < ElaboratedType > ( QTy ) ;
QT = Ty - > desugar ( ) ;
return true ;
2012-11-30 01:40:44 +04:00
}
//
// Conditionally sugared types.
//
case Type : : TypeOfExpr : {
const TypeOfExprType * Ty = llvm : : cast < TypeOfExprType > ( QTy ) ;
if ( Ty - > isSugared ( ) ) {
QT = Ty - > desugar ( ) ;
return true ;
}
return false ;
}
case Type : : Decltype : {
const DecltypeType * Ty = llvm : : cast < DecltypeType > ( QTy ) ;
if ( Ty - > isSugared ( ) ) {
QT = Ty - > desugar ( ) ;
return true ;
}
return false ;
}
case Type : : UnaryTransform : {
return false ;
//const UnaryTransformType* Ty = llvm::cast<UnaryTransformType>(QTy);
//if (Ty->isSugared()) {
// QT = Ty->desugar();
// return true;
//}
//return false;
}
case Type : : Auto : {
return false ;
//const AutoType* Ty = llvm::cast<AutoType>(QTy);
//if (Ty->isSugared()) {
// QT = Ty->desugar();
// return true;
//}
//return false;
}
case Type : : TemplateSpecialization : {
return false ;
//const TemplateSpecializationType* Ty =
// llvm::cast<TemplateSpecializationType>(QTy);
//if (Ty->isSugared()) {
// QT = Ty->desugar();
// return true;
//}
return false ;
}
// Not a sugared type.
default : {
break ;
}
}
return false ;
}
2012-12-02 00:37:09 +04:00
bool Transform : : SingleStepPartiallyDesugarType ( QualType & QT ,
const ASTContext & Context ) {
Qualifiers quals = QT . getQualifiers ( ) ;
bool desugared = SingleStepPartiallyDesugarTypeImpl ( QT ) ;
if ( desugared ) {
// If the types has been desugared it also lost its qualifiers.
QT = Context . getQualifiedType ( QT , quals ) ;
}
return desugared ;
}
2013-08-29 02:02:57 +04:00
static QualType GetPartiallyDesugaredTypeImpl ( const ASTContext & Ctx ,
2013-09-03 08:44:24 +04:00
QualType QT , const Transform : : Config & TypeConfig ,
2013-08-29 02:02:57 +04:00
bool fullyQualifyType ,
bool fullyQualifyTmpltArg )
2012-11-30 01:40:44 +04:00
{
// If there are no constraints, then use the standard desugaring.
2013-09-03 08:44:24 +04:00
if ( TypeConfig . empty ( ) & & ! fullyQualifyType & & ! fullyQualifyTmpltArg )
2012-09-05 13:37:39 +04:00
return QT . getDesugaredType ( Ctx ) ;
// In case of Int_t* we need to strip the pointer first, desugar and attach
// the pointer once again.
2012-10-19 17:24:46 +04:00
if ( isa < PointerType > ( QT . getTypePtr ( ) ) ) {
2012-09-05 13:37:39 +04:00
// Get the qualifiers.
Qualifiers quals = QT . getQualifiers ( ) ;
2013-09-03 08:44:24 +04:00
QT = GetPartiallyDesugaredTypeImpl ( Ctx , QT - > getPointeeType ( ) , TypeConfig ,
2013-08-29 02:02:57 +04:00
fullyQualifyType , fullyQualifyTmpltArg ) ;
2012-09-05 13:37:39 +04:00
QT = Ctx . getPointerType ( QT ) ;
// Add back the qualifiers.
QT = Ctx . getQualifiedType ( QT , quals ) ;
2012-09-23 01:30:24 +04:00
return QT ;
2012-09-05 13:37:39 +04:00
}
2013-02-08 02:56:10 +04:00
2013-02-12 22:38:58 +04:00
while ( isa < SubstTemplateTypeParmType > ( QT . getTypePtr ( ) ) ) {
// Get the qualifiers.
Qualifiers quals = QT . getQualifiers ( ) ;
2013-02-08 02:56:10 +04:00
QT = dyn_cast < SubstTemplateTypeParmType > ( QT . getTypePtr ( ) ) - > desugar ( ) ;
2013-02-12 22:38:58 +04:00
// Add back the qualifiers.
QT = Ctx . getQualifiedType ( QT , quals ) ;
2013-02-08 02:56:10 +04:00
}
2012-09-05 13:37:39 +04:00
// In case of Int_t& we need to strip the pointer first, desugar and attach
// the pointer once again.
2012-10-19 17:24:46 +04:00
if ( isa < ReferenceType > ( QT . getTypePtr ( ) ) ) {
2012-09-05 13:37:39 +04:00
// Get the qualifiers.
bool isLValueRefTy = isa < LValueReferenceType > ( QT . getTypePtr ( ) ) ;
Qualifiers quals = QT . getQualifiers ( ) ;
2013-09-03 08:44:24 +04:00
QT = GetPartiallyDesugaredTypeImpl ( Ctx , QT - > getPointeeType ( ) , TypeConfig ,
2013-08-29 02:02:57 +04:00
fullyQualifyType , fullyQualifyTmpltArg ) ;
2012-11-30 01:40:44 +04:00
// Add the r- or l-value reference type back to the desugared one.
2012-09-05 13:37:39 +04:00
if ( isLValueRefTy )
QT = Ctx . getLValueReferenceType ( QT ) ;
else
QT = Ctx . getRValueReferenceType ( QT ) ;
// Add back the qualifiers.
QT = Ctx . getQualifiedType ( QT , quals ) ;
2012-09-23 01:30:24 +04:00
return QT ;
}
// If the type is elaborated, first remove the prefix and then
// when we are done we will as needed add back the (new) prefix.
// for example for std::vector<int>::iterator, we work on
// just 'iterator' (which remember which scope its from)
// and remove the typedef to get (for example),
// __gnu_cxx::__normal_iterator
// which is *not* in the std::vector<int> scope and it is
// the __gnu__cxx part we should use as the prefix.
// NOTE: however we problably want to add the std::vector typedefs
// to the list of things to skip!
NestedNameSpecifier * original_prefix = 0 ;
2013-03-01 22:06:58 +04:00
Qualifiers prefix_qualifiers ;
2012-09-23 01:30:24 +04:00
const ElaboratedType * etype_input
2013-03-01 22:12:48 +04:00
= dyn_cast < ElaboratedType > ( QT . getTypePtr ( ) ) ;
2012-09-23 01:30:24 +04:00
if ( etype_input ) {
2012-12-01 22:02:54 +04:00
// Intentionally, we do not care about the other compononent of
// the elaborated type (the keyword) as part of the partial
// desugaring (and/or name normaliztation) is to remove it.
2012-09-23 01:30:24 +04:00
original_prefix = etype_input - > getQualifier ( ) ;
2012-10-26 23:51:56 +04:00
if ( original_prefix ) {
const NamespaceDecl * ns = original_prefix - > getAsNamespace ( ) ;
if ( ! ( ns & & ns - > isAnonymousNamespace ( ) ) ) {
// We have to also desugar the prefix unless
// it does not have a name (anonymous namespaces).
2013-08-29 02:02:57 +04:00
fullyQualifyType = true ;
2012-10-26 23:51:56 +04:00
prefix_qualifiers = QT . getLocalQualifiers ( ) ;
QT = QualType ( etype_input - > getNamedType ( ) . getTypePtr ( ) , 0 ) ;
} else {
original_prefix = 0 ;
}
}
2012-09-05 13:37:39 +04:00
}
2012-11-30 01:40:44 +04:00
// Desugar QT until we cannot desugar any more, or
// we hit one of the special typedefs.
while ( 1 ) {
if ( llvm : : isa < TypedefType > ( QT . getTypePtr ( ) ) & &
2013-09-03 08:44:24 +04:00
ShouldKeepTypedef ( QT , TypeConfig . m_toSkip ) ) {
2013-08-29 02:02:57 +04:00
if ( ! fullyQualifyType & & ! fullyQualifyTmpltArg ) {
2012-11-30 01:40:44 +04:00
return QT ;
}
2012-11-28 21:18:16 +04:00
// We might have stripped the namespace/scope part,
2012-11-30 01:40:44 +04:00
// so we must go on to add it back.
2012-11-28 21:18:16 +04:00
break ;
2012-11-30 01:40:44 +04:00
}
2013-08-29 02:02:57 +04:00
bool wasDesugared = Transform : : SingleStepPartiallyDesugarType ( QT , Ctx ) ;
2013-09-03 08:44:24 +04:00
// 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 ;
}
2012-11-30 01:40:44 +04:00
if ( ! wasDesugared ) {
// No more work to do, stop now.
break ;
}
2012-11-28 20:14:29 +04:00
}
2012-09-23 01:30:24 +04:00
2012-10-19 17:24:46 +04:00
// If we have a reference or pointer we still need to
// desugar what they point to.
2013-03-01 21:59:59 +04:00
if ( isa < PointerType > ( QT . getTypePtr ( ) ) | |
2012-10-19 17:24:46 +04:00
isa < ReferenceType > ( QT . getTypePtr ( ) ) ) {
2013-09-03 08:44:24 +04:00
return GetPartiallyDesugaredTypeImpl ( Ctx , QT , TypeConfig ,
2013-08-29 02:02:57 +04:00
fullyQualifyType ,
fullyQualifyTmpltArg ) ;
2012-10-19 17:24:46 +04:00
}
2012-09-05 13:37:39 +04:00
NestedNameSpecifier * prefix = 0 ;
const ElaboratedType * etype
2013-03-01 22:12:48 +04:00
= dyn_cast < ElaboratedType > ( QT . getTypePtr ( ) ) ;
2012-09-05 13:37:39 +04:00
if ( etype ) {
2012-12-11 12:26:00 +04:00
2013-09-03 08:44:24 +04:00
prefix = SelectPrefix ( Ctx , etype , original_prefix , TypeConfig ) ;
2012-12-11 12:26:00 +04:00
2012-09-25 23:35:24 +04:00
prefix_qualifiers . addQualifiers ( QT . getLocalQualifiers ( ) ) ;
QT = QualType ( etype - > getNamedType ( ) . getTypePtr ( ) , 0 ) ;
2012-12-11 12:26:00 +04:00
2013-08-29 02:02:57 +04:00
} else if ( fullyQualifyType ) {
2012-09-05 13:37:39 +04:00
// 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 ...
2012-09-23 01:30:24 +04:00
Decl * decl = 0 ;
const TypedefType * typedeftype =
2013-03-01 22:12:48 +04:00
dyn_cast_or_null < TypedefType > ( QT . getTypePtr ( ) ) ;
2012-09-23 01:30:24 +04:00
if ( typedeftype ) {
decl = typedeftype - > getDecl ( ) ;
} else {
// There are probably other cases ...
const TagType * tagdecltype =
2013-03-01 22:12:48 +04:00
dyn_cast_or_null < TagType > ( QT . getTypePtr ( ) ) ;
2012-09-23 01:30:24 +04:00
if ( tagdecltype ) {
decl = tagdecltype - > getDecl ( ) ;
} else {
decl = QT - > getAsCXXRecordDecl ( ) ;
}
}
if ( decl ) {
NamedDecl * outer
2013-03-01 22:12:48 +04:00
= dyn_cast_or_null < NamedDecl > ( decl - > getDeclContext ( ) ) ;
2012-10-26 23:51:56 +04:00
NamespaceDecl * outer_ns
2013-03-01 22:12:48 +04:00
= dyn_cast_or_null < NamespaceDecl > ( decl - > getDeclContext ( ) ) ;
2012-10-26 23:51:56 +04:00
if ( outer
& & ! ( outer_ns & & outer_ns - > isAnonymousNamespace ( ) )
& & outer - > getName ( ) . size ( ) ) {
2012-09-26 12:01:21 +04:00
if ( original_prefix ) {
2013-03-01 22:06:58 +04:00
const Type * oldtype = original_prefix - > getAsType ( ) ;
2012-09-26 12:01:21 +04:00
if ( oldtype ) {
if ( oldtype - > getAsCXXRecordDecl ( ) = = outer ) {
// Same type, use the original spelling
2013-09-03 08:44:24 +04:00
prefix = GetPartiallyDesugaredNNS ( Ctx , original_prefix , TypeConfig ) ;
2012-09-26 12:01:21 +04:00
outer = 0 ; // Cancel the later creation.
}
} else {
const NamespaceDecl * old_ns = original_prefix - > getAsNamespace ( ) ;
if ( old_ns ) {
old_ns = old_ns - > getCanonicalDecl ( ) ;
}
else if ( NamespaceAliasDecl * alias =
original_prefix - > getAsNamespaceAlias ( ) )
{
old_ns = alias - > getNamespace ( ) - > getCanonicalDecl ( ) ;
}
2013-03-01 22:12:48 +04:00
const NamespaceDecl * new_ns = dyn_cast < NamespaceDecl > ( outer ) ;
2012-09-26 12:01:21 +04:00
if ( new_ns ) new_ns = new_ns - > getCanonicalDecl ( ) ;
if ( old_ns = = new_ns ) {
// This is the same namespace, use the original prefix
// as a starting point.
2013-03-01 21:59:59 +04:00
prefix = GetFullyQualifiedNameSpecifier ( Ctx , original_prefix ) ;
2012-09-26 12:01:21 +04:00
outer = 0 ; // Cancel the later creation.
}
2012-09-23 01:30:24 +04:00
}
2012-09-26 12:01:21 +04:00
} else { // if (!original_prefix)
// move the qualifiers on the outer type (avoid 'std::const string'!)
prefix_qualifiers = QT . getLocalQualifiers ( ) ;
QT = QualType ( QT . getTypePtr ( ) , 0 ) ;
2012-09-23 01:30:24 +04:00
}
2012-09-26 12:01:21 +04:00
if ( outer ) {
if ( decl - > getDeclContext ( ) - > isNamespace ( ) ) {
prefix = CreateNestedNameSpecifier ( Ctx ,
2013-03-01 21:59:59 +04:00
dyn_cast < NamespaceDecl > ( outer ) ) ;
2012-09-26 12:01:21 +04:00
} else {
2012-11-21 03:19:48 +04:00
// We should only create the nested name specifier
// if the outer scope is really a TagDecl.
// It could also be a CXXMethod for example.
2013-03-01 22:12:48 +04:00
TagDecl * tdecl = dyn_cast < TagDecl > ( outer ) ;
2012-12-01 22:02:54 +04:00
if ( tdecl ) {
prefix = CreateNestedNameSpecifier ( Ctx , tdecl ) ;
2013-09-03 08:44:24 +04:00
prefix = GetPartiallyDesugaredNNS ( Ctx , prefix , TypeConfig ) ;
2012-12-01 22:02:54 +04:00
}
2012-09-26 12:01:21 +04:00
}
2012-09-23 01:30:24 +04:00
}
}
2012-09-05 13:37:39 +04:00
}
}
// In case of template specializations iterate over the arguments and
// desugar them as well.
if ( const TemplateSpecializationType * TST
= dyn_cast < const TemplateSpecializationType > ( QT . getTypePtr ( ) ) ) {
bool mightHaveChanged = false ;
llvm : : SmallVector < TemplateArgument , 4 > desArgs ;
for ( TemplateSpecializationType : : iterator I = TST - > begin ( ) , E = TST - > end ( ) ;
I ! = E ; + + I ) {
2012-11-17 11:36:22 +04:00
if ( I - > getKind ( ) ! = TemplateArgument : : Type ) {
2012-09-28 16:28:14 +04:00
desArgs . push_back ( * I ) ;
continue ;
2012-09-05 13:37:39 +04:00
}
2012-09-28 16:28:14 +04:00
QualType SubTy = I - > getAsType ( ) ;
2012-09-05 13:37:39 +04:00
// Check if the type needs more desugaring and recurse.
if ( isa < TypedefType > ( SubTy )
| | isa < TemplateSpecializationType > ( SubTy )
2012-09-25 23:35:24 +04:00
| | isa < ElaboratedType > ( SubTy )
2013-08-29 02:02:57 +04:00
| | fullyQualifyTmpltArg ) {
2012-09-05 13:37:39 +04:00
mightHaveChanged = true ;
2013-08-29 02:02:57 +04:00
desArgs . push_back ( TemplateArgument ( GetPartiallyDesugaredTypeImpl ( Ctx ,
2012-09-05 13:37:39 +04:00
SubTy ,
2013-09-03 08:44:24 +04:00
TypeConfig ,
2013-08-29 02:02:57 +04:00
fullyQualifyType ,
fullyQualifyTmpltArg ) ) ) ;
} else
2012-09-05 13:37:39 +04:00
desArgs . push_back ( * I ) ;
}
// If desugaring happened allocate new type in the AST.
if ( mightHaveChanged ) {
2012-09-26 12:01:21 +04:00
Qualifiers qualifiers = QT . getLocalQualifiers ( ) ;
2012-09-05 13:37:39 +04:00
QT = Ctx . getTemplateSpecializationType ( TST - > getTemplateName ( ) ,
2012-09-19 16:39:06 +04:00
desArgs . data ( ) ,
desArgs . size ( ) ,
TST - > getCanonicalTypeInternal ( ) ) ;
2012-09-26 12:01:21 +04:00
QT = Ctx . getQualifiedType ( QT , qualifiers ) ;
2012-09-05 13:37:39 +04:00
}
2013-08-29 02:02:57 +04:00
} else if ( fullyQualifyTmpltArg ) {
2013-02-08 02:56:10 +04:00
if ( const RecordType * TSTRecord
= dyn_cast < const RecordType > ( QT . getTypePtr ( ) ) ) {
// We are asked to fully qualify and we have a Record Type,
// which can point to a template instantiation with no sugar in any of
// its template argument, however we still need to fully qualify them.
if ( const ClassTemplateSpecializationDecl * TSTdecl =
dyn_cast < ClassTemplateSpecializationDecl > ( TSTRecord - > getDecl ( ) ) )
{
const TemplateArgumentList & templateArgs
= TSTdecl - > getTemplateArgs ( ) ;
bool mightHaveChanged = false ;
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.
if ( isa < TypedefType > ( SubTy )
| | isa < TemplateSpecializationType > ( SubTy )
| | isa < ElaboratedType > ( SubTy )
2013-08-29 02:02:57 +04:00
| | fullyQualifyTmpltArg ) {
2013-02-08 02:56:10 +04:00
mightHaveChanged = true ;
2013-08-29 02:02:57 +04:00
desArgs . push_back ( TemplateArgument (
GetPartiallyDesugaredTypeImpl ( Ctx ,
SubTy ,
2013-09-03 08:44:24 +04:00
TypeConfig ,
2013-08-29 02:02:57 +04:00
/*fullyQualifyType=*/ true ,
/*fullyQualifyTmpltArg=*/ true ) ) ) ;
2013-02-08 02:56:10 +04:00
} else
desArgs . push_back ( templateArgs [ I ] ) ;
}
// If desugaring happened allocate new type in the AST.
if ( mightHaveChanged ) {
Qualifiers qualifiers = QT . getLocalQualifiers ( ) ;
QT = Ctx . getTemplateSpecializationType ( TemplateName ( TSTdecl - > getSpecializedTemplate ( ) ) ,
desArgs . data ( ) ,
desArgs . size ( ) ,
TSTRecord - > getCanonicalTypeInternal ( ) ) ;
QT = Ctx . getQualifiedType ( QT , qualifiers ) ;
}
}
}
2012-09-05 13:37:39 +04:00
}
if ( prefix ) {
2012-12-01 22:02:54 +04:00
// We intentionally always use ETK_None, we never want
// the keyword (humm ... what about anonymous types?)
2012-09-25 23:35:24 +04:00
QT = Ctx . getElaboratedType ( ETK_None , prefix , QT ) ;
2012-09-26 12:01:21 +04:00
QT = Ctx . getQualifiedType ( QT , prefix_qualifiers ) ;
2012-09-05 13:37:39 +04:00
}
return QT ;
}
2013-08-29 02:02:57 +04:00
QualType Transform : : GetPartiallyDesugaredType ( const ASTContext & Ctx ,
2013-09-03 08:44:24 +04:00
QualType QT , const Transform : : Config & TypeConfig ,
2013-08-29 02:02:57 +04:00
bool fullyQualify /*=true*/ )
{
2013-09-03 08:44:24 +04:00
return GetPartiallyDesugaredTypeImpl ( Ctx , QT , TypeConfig ,
2013-08-29 02:02:57 +04:00
/*qualifyType*/ fullyQualify ,
/*qualifyTmpltArg*/ fullyQualify ) ;
}
2012-09-05 13:37:39 +04:00
NamespaceDecl * Lookup : : Namespace ( Sema * S , const char * Name ,
2012-11-20 23:13:06 +04:00
const DeclContext * Within ) {
2012-09-05 13:37:39 +04:00
DeclarationName DName = & S - > Context . Idents . get ( Name ) ;
LookupResult R ( * S , DName , SourceLocation ( ) ,
Sema : : LookupNestedNameSpecifierName ) ;
if ( ! Within )
S - > LookupName ( R , S - > TUScope ) ;
else
2012-11-20 23:13:06 +04:00
S - > LookupQualifiedName ( R , const_cast < DeclContext * > ( Within ) ) ;
2012-09-05 13:37:39 +04:00
if ( R . empty ( ) )
return 0 ;
R . resolveKind ( ) ;
return dyn_cast < NamespaceDecl > ( R . getFoundDecl ( ) ) ;
}
2012-11-20 23:13:06 +04:00
NamedDecl * Lookup : : Named ( Sema * S , const char * Name ,
const DeclContext * Within ) {
2012-09-05 13:37:39 +04:00
DeclarationName DName = & S - > Context . Idents . get ( Name ) ;
2012-10-09 13:41:26 +04:00
return Lookup : : Named ( S , DName , Within ) ;
}
2012-09-05 13:37:39 +04:00
2012-10-09 13:41:26 +04:00
NamedDecl * Lookup : : Named ( Sema * S , const DeclarationName & Name ,
2012-11-20 23:13:06 +04:00
const DeclContext * Within ) {
2012-10-09 13:41:26 +04:00
LookupResult R ( * S , Name , SourceLocation ( ) , Sema : : LookupOrdinaryName ,
2012-09-05 13:37:39 +04:00
Sema : : ForRedeclaration ) ;
if ( ! Within )
S - > LookupName ( R , S - > TUScope ) ;
else
2012-11-20 23:13:06 +04:00
S - > LookupQualifiedName ( R , const_cast < DeclContext * > ( Within ) ) ;
2012-09-05 13:37:39 +04:00
if ( R . empty ( ) )
return 0 ;
R . resolveKind ( ) ;
return R . getFoundDecl ( ) ;
}
} // end namespace utils
} // end namespace cling