2012-09-05 13:37:39 +04:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author: Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
2014-01-07 14:08:37 +04:00
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
2012-09-05 13:37:39 +04:00
//------------------------------------------------------------------------------
# include "cling/Utils/AST.h"
# include "clang/AST/ASTContext.h"
# include "clang/AST/DeclarationName.h"
2013-10-24 22:14:19 +04:00
# include "clang/AST/GlobalDecl.h"
2012-09-05 13:37:39 +04:00
# 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"
2014-06-06 12:26:05 +04:00
# include "clang/AST/Mangle.h"
2013-10-23 02:08:14 +04:00
2014-08-14 14:29:27 +04:00
# include <memory>
2013-02-14 21:23:47 +04:00
# include <stdio.h>
2013-10-23 02:08:14 +04:00
2012-09-05 13:37:39 +04:00
using namespace clang ;
2018-09-21 14:16:09 +03:00
namespace {
template < typename D >
static D * LookupResult2Decl ( clang : : LookupResult & R )
{
if ( R . empty ( ) )
return 0 ;
R . resolveKind ( ) ;
if ( R . isSingleResult ( ) )
return dyn_cast < D > ( R . getFoundDecl ( ) ) ;
return ( D * ) - 1 ;
}
}
2012-09-05 13:37:39 +04:00
namespace cling {
namespace utils {
2012-10-15 20:57:53 +04:00
2013-08-29 02:02:57 +04:00
static
2013-12-05 19:21:12 +04:00
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 ,
2013-12-05 19:21:12 +04:00
NestedNameSpecifier * scope ,
2013-09-03 08:44:24 +04:00
const Transform : : Config & TypeConfig ) ;
2013-08-29 02:02:57 +04:00
2014-09-17 22:37:11 +04:00
static NestedNameSpecifier *
CreateNestedNameSpecifierForScopeOf ( const ASTContext & Ctx ,
const Decl * decl ,
bool FullyQualified ) ;
static
NestedNameSpecifier * GetFullyQualifiedNameSpecifier ( const ASTContext & Ctx ,
NestedNameSpecifier * scope ) ;
2016-08-30 11:07:09 +03:00
bool Analyze : : IsWrapper ( const FunctionDecl * ND ) {
2012-10-17 12:52:24 +04:00
if ( ! ND )
return false ;
2019-03-25 18:39:32 +03:00
if ( ! ND - > getDeclName ( ) . isIdentifier ( ) )
return false ;
2012-10-17 12:52:24 +04:00
2019-03-25 18:39:32 +03:00
return ND - > getName ( ) . startswith ( Synthesize : : UniquePrefix ) ;
2012-10-17 12:52:24 +04:00
}
2013-12-04 19:39:43 +04:00
void Analyze : : maybeMangleDeclName ( const GlobalDecl & GD ,
2013-10-24 22:14:19 +04:00
std : : string & mangledName ) {
2013-12-04 19:39:43 +04:00
// copied and adapted from CodeGen::CodeGenModule::getMangledName
2013-10-25 20:41:14 +04:00
2013-12-04 19:39:43 +04:00
NamedDecl * D
= cast < NamedDecl > ( const_cast < Decl * > ( GD . getDecl ( ) ) ) ;
2014-08-14 14:29:27 +04:00
std : : unique_ptr < MangleContext > mangleCtx ;
2013-10-23 02:08:14 +04:00
mangleCtx . reset ( D - > getASTContext ( ) . createMangleContext ( ) ) ;
2013-10-25 20:41:14 +04:00
if ( ! mangleCtx - > shouldMangleDeclName ( D ) ) {
IdentifierInfo * II = D - > getIdentifier ( ) ;
assert ( II & & " Attempt to mangle unnamed decl. " ) ;
mangledName = II - > getName ( ) ;
return ;
}
2013-12-05 19:21:12 +04:00
2013-10-25 01:59:15 +04:00
llvm : : raw_string_ostream RawStr ( mangledName ) ;
switch ( D - > getKind ( ) ) {
case Decl : : CXXConstructor :
//Ctor_Complete, // Complete object ctor
//Ctor_Base, // Base object ctor
//Ctor_CompleteAllocating // Complete object allocating ctor (unused)
2013-12-05 19:21:12 +04:00
mangleCtx - > mangleCXXCtor ( cast < CXXConstructorDecl > ( D ) ,
2013-10-25 01:59:15 +04:00
GD . getCtorType ( ) , RawStr ) ;
break ;
2013-10-23 02:08:14 +04:00
2013-10-25 01:59:15 +04:00
case Decl : : CXXDestructor :
//Dtor_Deleting, // Deleting dtor
//Dtor_Complete, // Complete object dtor
//Dtor_Base // Base object dtor
2016-12-01 20:30:25 +03:00
# if defined(LLVM_ON_WIN32)
// MicrosoftMangle.cpp:954 calls llvm_unreachable when mangling Dtor_Comdat
if ( GD . getDtorType ( ) = = Dtor_Comdat ) {
if ( const IdentifierInfo * II = D - > getIdentifier ( ) )
RawStr < < II - > getName ( ) ;
} else
# endif
{
mangleCtx - > mangleCXXDtor ( cast < CXXDestructorDecl > ( D ) ,
GD . getDtorType ( ) , RawStr ) ;
}
2013-10-25 01:59:15 +04:00
break ;
2013-10-23 02:08:14 +04:00
2013-10-25 01:59:15 +04:00
default :
mangleCtx - > mangleName ( D , RawStr ) ;
break ;
2013-10-23 02:08:14 +04:00
}
2013-10-25 01:59:15 +04:00
RawStr . flush ( ) ;
2013-10-23 02:08:14 +04:00
}
2013-12-05 19:21:12 +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 ] ) )
2013-12-05 19:21:12 +04:00
break ;
2012-10-19 13:22:36 +04:00
}
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.
2013-12-05 19:21:12 +04:00
SourceLocation Loc
2012-10-19 13:22:36 +04:00
= newBody [ indexOfLastExpr ] - > getLocEnd ( ) . getLocWithOffset ( 1 ) ;
2014-06-06 12:18:32 +04:00
Expr * DRE = S - > BuildDeclRefExpr ( VD , VDTy , VK_LValue , Loc ) . get ( ) ;
2012-10-19 13:22:36 +04:00
assert ( DRE & & " Cannot be null " ) ;
indexOfLastExpr + + ;
newBody . insert ( newBody . begin ( ) + indexOfLastExpr , DRE ) ;
// Attach the new body (note: it does dealloc/alloc of all nodes)
2016-04-25 16:42:56 +03:00
CS - > setStmts ( S - > getASTContext ( ) , newBody ) ;
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 " ;
2012-10-17 12:52:24 +04:00
2016-08-06 05:06:26 +03:00
IntegerLiteral * Synthesize : : IntegerLiteralExpr ( ASTContext & C , uintptr_t Ptr ) {
const llvm : : APInt Addr ( 8 * sizeof ( void * ) , Ptr ) ;
return IntegerLiteral : : Create ( C , Addr , C . getUIntPtrType ( ) ,
SourceLocation ( ) ) ;
}
Expr * Synthesize : : CStyleCastPtrExpr ( Sema * S , QualType Ty , uintptr_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 ( ) ) ;
2013-12-05 19:21:12 +04:00
Expr * Result
2014-06-06 12:18:32 +04:00
= S - > BuildCStyleCastExpr ( SourceLocation ( ) , TSI , SourceLocation ( ) , E ) . get ( ) ;
2012-09-05 13:37:39 +04:00
assert ( Result & & " Cannot create CStyleCastPtrExpr " ) ;
return Result ;
}
2014-09-17 22:37:11 +04:00
static bool
GetFullyQualifiedTemplateName ( const ASTContext & Ctx , TemplateName & tname ) {
2014-09-18 01:18:57 +04:00
bool changed = false ;
NestedNameSpecifier * NNS = 0 ;
TemplateDecl * argtdecl = tname . getAsTemplateDecl ( ) ;
QualifiedTemplateName * qtname = tname . getAsQualifiedTemplateName ( ) ;
if ( qtname & & ! qtname - > hasTemplateKeyword ( ) ) {
NNS = qtname - > getQualifier ( ) ;
NestedNameSpecifier * qNNS = GetFullyQualifiedNameSpecifier ( Ctx , NNS ) ;
if ( qNNS ! = NNS ) {
2014-09-17 22:37:11 +04:00
changed = true ;
2014-09-18 01:18:57 +04:00
NNS = qNNS ;
} else {
NNS = 0 ;
}
} else {
NNS = CreateNestedNameSpecifierForScopeOf ( Ctx , argtdecl , true ) ;
}
if ( NNS ) {
tname = Ctx . getQualifiedTemplateName ( NNS ,
/*TemplateKeyword=*/ false ,
argtdecl ) ;
changed = true ;
}
return changed ;
2014-09-17 22:37:11 +04:00
}
static bool
2015-10-28 18:35:50 +03:00
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 ;
}
2015-10-28 20:19:19 +03:00
} else if ( arg . getKind ( ) = = TemplateArgument : : Pack ) {
SmallVector < TemplateArgument , 2 > desArgs ;
for ( auto I = arg . pack_begin ( ) , E = arg . pack_end ( ) ; I ! = E ; + + I ) {
TemplateArgument pack_arg ( * I ) ;
changed = GetFullyQualifiedTemplateArgument ( Ctx , pack_arg ) ;
desArgs . push_back ( pack_arg ) ;
}
if ( changed ) {
// The allocator in ASTContext is mutable ...
// Keep the argument const to be inline will all the other interfaces
// like: NestedNameSpecifier::Create
ASTContext & mutableCtx ( const_cast < ASTContext & > ( Ctx ) ) ;
2016-06-15 12:31:15 +03:00
arg = TemplateArgument : : CreatePackCopy ( mutableCtx , desArgs ) ;
2015-10-28 20:19:19 +03:00
}
2015-10-28 18:35:50 +03:00
}
return changed ;
2014-09-17 22:37:11 +04:00
}
2013-12-05 19:21:12 +04:00
static const Type *
GetFullyQualifiedLocalType ( const ASTContext & Ctx ,
const Type * typeptr ) {
2013-12-04 19:39:43 +04:00
// We really just want to handle the template parameter if any ....
// In case of template specializations iterate over the arguments and
// fully qualify them as well.
2013-12-05 19:21:12 +04:00
if ( const TemplateSpecializationType * TST
= llvm : : dyn_cast < const TemplateSpecializationType > ( typeptr ) ) {
2013-12-04 19:39:43 +04:00
bool mightHaveChanged = false ;
2013-12-05 19:21:12 +04:00
llvm : : SmallVector < TemplateArgument , 4 > desArgs ;
for ( TemplateSpecializationType : : iterator
I = TST - > begin ( ) , E = TST - > end ( ) ;
2013-12-04 19:39:43 +04:00
I ! = E ; + + I ) {
2014-09-17 22:37:11 +04:00
// cheap to copy and potentially modified by
// GetFullyQualifedTemplateArgument
TemplateArgument arg ( * I ) ;
mightHaveChanged | = GetFullyQualifiedTemplateArgument ( Ctx , arg ) ;
desArgs . push_back ( arg ) ;
2013-12-04 19:39:43 +04:00
}
// If desugaring happened allocate new type in the AST.
if ( mightHaveChanged ) {
2013-12-05 19:21:12 +04:00
QualType QT
= Ctx . getTemplateSpecializationType ( TST - > getTemplateName ( ) ,
2017-05-18 16:16:30 +03:00
desArgs ,
2013-12-05 19:21:12 +04:00
TST - > getCanonicalTypeInternal ( ) ) ;
2013-12-04 19:39:43 +04:00
return QT . getTypePtr ( ) ;
}
2013-12-05 19:21:12 +04:00
} else if ( const RecordType * TSTRecord
= llvm : : dyn_cast < const RecordType > ( typeptr ) ) {
2013-12-04 19:39:43 +04:00
// 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.
2013-12-05 19:21:12 +04:00
if ( const ClassTemplateSpecializationDecl * TSTdecl =
llvm : : dyn_cast < ClassTemplateSpecializationDecl > ( TSTRecord - > getDecl ( ) ) )
2013-12-04 19:39:43 +04:00
{
2013-12-05 19:21:12 +04:00
const TemplateArgumentList & templateArgs
2013-12-04 19:39:43 +04:00
= TSTdecl - > getTemplateArgs ( ) ;
bool mightHaveChanged = false ;
2013-12-05 19:21:12 +04:00
llvm : : SmallVector < TemplateArgument , 4 > desArgs ;
2013-12-04 19:39:43 +04:00
for ( unsigned int I = 0 , E = templateArgs . size ( ) ;
I ! = E ; + + I ) {
2014-09-17 22:37:11 +04:00
// cheap to copy and potentially modified by
// GetFullyQualifedTemplateArgument
TemplateArgument arg ( templateArgs [ I ] ) ;
mightHaveChanged | = GetFullyQualifiedTemplateArgument ( Ctx , arg ) ;
desArgs . push_back ( arg ) ;
2013-12-04 19:39:43 +04:00
}
2014-09-17 22:37:11 +04:00
2013-12-04 19:39:43 +04:00
// If desugaring happened allocate new type in the AST.
if ( mightHaveChanged ) {
2013-12-05 19:21:12 +04:00
TemplateName TN ( TSTdecl - > getSpecializedTemplate ( ) ) ;
QualType QT
2017-05-18 16:16:30 +03:00
= Ctx . getTemplateSpecializationType ( TN , desArgs ,
2013-12-05 19:21:12 +04:00
TSTRecord - > getCanonicalTypeInternal ( ) ) ;
2013-12-04 19:39:43 +04:00
return QT . getTypePtr ( ) ;
}
}
2012-12-11 12:26:00 +04:00
}
2013-12-04 19:39:43 +04:00
return typeptr ;
2012-12-11 12:26:00 +04:00
}
2013-12-04 19:39:43 +04:00
static NestedNameSpecifier * CreateOuterNNS ( const ASTContext & Ctx ,
2013-12-04 21:26:23 +04:00
const Decl * D ,
bool FullyQualify ) {
2013-12-04 19:39:43 +04:00
const DeclContext * DC = D - > getDeclContext ( ) ;
if ( const NamespaceDecl * NS = dyn_cast < NamespaceDecl > ( DC ) ) {
2014-01-12 19:59:12 +04:00
while ( NS & & NS - > isInline ( ) ) {
// Ignore inline namespace;
NS = dyn_cast_or_null < NamespaceDecl > ( NS - > getDeclContext ( ) ) ;
}
2020-10-02 15:34:43 +03:00
if ( NS & & NS - > getDeclName ( ) )
2013-12-04 19:39:43 +04:00
return TypeName : : CreateNestedNameSpecifier ( Ctx , NS ) ;
2020-10-02 15:34:43 +03:00
return nullptr ; // no starting '::', no anonymous
2013-12-04 19:39:43 +04:00
} else if ( const TagDecl * TD = dyn_cast < TagDecl > ( DC ) ) {
2013-12-04 21:26:23 +04:00
return TypeName : : CreateNestedNameSpecifier ( Ctx , TD , FullyQualify ) ;
2014-01-06 21:04:47 +04:00
} else if ( const TypedefNameDecl * TDD = dyn_cast < TypedefNameDecl > ( DC ) ) {
return TypeName : : CreateNestedNameSpecifier ( Ctx , TDD , FullyQualify ) ;
2012-12-11 12:26:00 +04:00
}
2020-10-02 15:34:43 +03:00
return nullptr ; // no starting '::'
2012-12-11 12:26:00 +04:00
}
2013-12-04 19:39:43 +04:00
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
2014-01-06 21:04:47 +04:00
if ( scope - > getKind ( ) = = NestedNameSpecifier : : Global ) {
// Already fully qualified.
2013-12-21 18:06:08 +04:00
return scope ;
2013-03-01 21:59:59 +04:00
}
2014-01-06 21:04:47 +04:00
if ( const Type * type = scope - > getAsType ( ) ) {
2013-03-01 21:59:59 +04:00
// Find decl context.
2014-01-06 21:04:47 +04:00
const TagDecl * TD = 0 ;
if ( const TagType * tagdecltype = dyn_cast < TagType > ( type ) ) {
TD = tagdecltype - > getDecl ( ) ;
2013-03-01 21:59:59 +04:00
} else {
2014-01-06 21:04:47 +04:00
TD = type - > getAsCXXRecordDecl ( ) ;
2013-03-01 21:59:59 +04:00
}
2014-01-06 21:04:47 +04:00
if ( TD ) {
return TypeName : : CreateNestedNameSpecifier ( Ctx , TD ,
true /*FullyQualified*/ ) ;
} else if ( const TypedefType * TDD = dyn_cast < TypedefType > ( type ) ) {
return TypeName : : CreateNestedNameSpecifier ( Ctx , TDD - > getDecl ( ) ,
true /*FullyQualified*/ ) ;
2013-03-01 21:59:59 +04:00
}
2014-01-06 21:04:47 +04:00
} else if ( const NamespaceDecl * NS = scope - > getAsNamespace ( ) ) {
return TypeName : : CreateNestedNameSpecifier ( Ctx , NS ) ;
} else if ( const NamespaceAliasDecl * alias = scope - > getAsNamespaceAlias ( ) ) {
const NamespaceDecl * NS = alias - > getNamespace ( ) - > getCanonicalDecl ( ) ;
return TypeName : : CreateNestedNameSpecifier ( Ctx , NS ) ;
2013-03-01 21:59:59 +04:00
}
return scope ;
}
2013-12-05 19:21:12 +04:00
2013-03-01 21:59:59 +04:00
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 ( ) ;
2013-09-06 06:36:00 +04:00
if ( NamespaceAliasDecl * alias =
2013-03-01 21:59:59 +04:00
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 {
2013-12-04 19:39:43 +04:00
prefix = TypeName : : CreateNestedNameSpecifier ( Ctx ,
2013-03-01 21:59:59 +04:00
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 ) {
2013-12-04 21:26:23 +04:00
prefix = TypeName : : CreateNestedNameSpecifier ( Ctx , tdecl ,
false /*FullyQualified*/ ) ;
2013-03-01 21:59:59 +04:00
}
}
} 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 ) {
2013-12-04 21:26:23 +04:00
prefix = TypeName : : CreateNestedNameSpecifier ( Ctx , tdecl ,
false /*FullyQualified*/ ) ;
2013-03-01 21:59:59 +04:00
}
}
}
} 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.
2013-12-05 19:21:12 +04:00
2012-12-11 12:26:00 +04:00
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 ( ) ;
2013-12-05 19:21:12 +04:00
if ( oldtype & &
2012-12-11 12:26:00 +04:00
// NOTE: Should we compare the RecordDecl instead?
oldtype - > getAsCXXRecordDecl ( ) = = newtype - > getAsCXXRecordDecl ( ) )
2013-12-05 19:21:12 +04:00
{
2012-12-11 12:26:00 +04:00
// 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-12-05 19:21:12 +04:00
}
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 ( ) ;
}
2013-12-05 19:21:12 +04:00
else if ( NamespaceAliasDecl * alias =
2012-12-11 12:26:00 +04:00
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-12-05 19:21:12 +04:00
2012-09-05 13:37:39 +04:00
static
2013-09-03 08:44:24 +04:00
NestedNameSpecifier * GetPartiallyDesugaredNNS ( const ASTContext & Ctx ,
2013-12-05 19:21:12 +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 ( ) ) {
2013-12-05 19:21:12 +04:00
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.
2013-12-05 19:21:12 +04:00
2013-03-01 21:59:59 +04:00
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-12-05 19:21:12 +04:00
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-12-13 02:03:43 +04:00
bool Analyze : : IsStdOrCompilerDetails ( const NamedDecl & decl )
{
// Return true if the TagType is a 'details' of the std implementation
// or declared within std.
// Details means (For now) declared in __gnu_cxx or starting with
// underscore.
IdentifierInfo * info = decl . getDeclName ( ) . getAsIdentifierInfo ( ) ;
if ( info & & info - > getNameStart ( ) [ 0 ] = = ' _ ' ) {
// We have a name starting by _, this is reserve for compiler
// implementation, so let's not desugar to it.
return true ;
}
// And let's check if it is in one of the know compiler implementation
// namespace.
const NamedDecl * outer = dyn_cast_or_null < NamedDecl > ( decl . getDeclContext ( ) ) ;
while ( outer & & outer - > getName ( ) . size ( ) ) {
if ( outer - > getName ( ) . compare ( " std " ) = = 0 | |
outer - > getName ( ) . compare ( " __gnu_cxx " ) = = 0 ) {
return true ;
}
outer = dyn_cast_or_null < NamedDecl > ( outer - > getDeclContext ( ) ) ;
}
return false ;
}
2014-02-01 04:23:32 +04:00
bool Analyze : : IsStdClass ( const clang : : NamedDecl & cl )
{
// Return true if the class or template is declared directly in the
// std namespace (modulo inline namespace).
2017-09-21 00:50:03 +03:00
return cl . getDeclContext ( ) - > isStdNamespace ( ) ;
2014-02-01 04:23:32 +04:00
}
2014-02-12 18:24:46 +04:00
// See Sema::PushOnScopeChains
bool Analyze : : isOnScopeChains ( const NamedDecl * ND , Sema & SemaR ) {
// Named decls without name shouldn't be in. Eg: struct {int a};
if ( ! ND - > getDeclName ( ) )
return false ;
// Out-of-line definitions shouldn't be pushed into scope in C++.
// Out-of-line variable and function definitions shouldn't even in C.
if ( ( isa < VarDecl > ( ND ) | | isa < FunctionDecl > ( ND ) ) & & ND - > isOutOfLine ( ) & &
! ND - > getDeclContext ( ) - > getRedeclContext ( ) - > Equals (
ND - > getLexicalDeclContext ( ) - > getRedeclContext ( ) ) )
return false ;
// Template instantiations should also not be pushed into scope.
if ( isa < FunctionDecl > ( ND ) & &
cast < FunctionDecl > ( ND ) - > isFunctionTemplateSpecialization ( ) )
return false ;
// Using directives are not registered onto the scope chain
if ( isa < UsingDirectiveDecl > ( ND ) )
return false ;
IdentifierResolver : : iterator
IDRi = SemaR . IdResolver . begin ( ND - > getDeclName ( ) ) ,
IDRiEnd = SemaR . IdResolver . end ( ) ;
for ( ; IDRi ! = IDRiEnd ; + + IDRi ) {
if ( ND = = * IDRi )
return true ;
}
// Check if the declaration is template instantiation, which is not in
// any DeclContext yet, because it came from
// Sema::PerformPendingInstantiations
// if (isa<FunctionDecl>(D) &&
// cast<FunctionDecl>(D)->getTemplateInstantiationPattern())
// return false;
return false ;
}
2014-02-01 04:45:59 +04:00
unsigned int
Transform : : Config : : DropDefaultArg ( clang : : TemplateDecl & Template ) const
{
/// Return the number of default argument to drop.
if ( Analyze : : IsStdClass ( Template ) ) {
static const char * stls [ ] = //container names
{ " vector " , " list " , " deque " , " map " , " multimap " , " set " , " multiset " , 0 } ;
static unsigned int values [ ] = //number of default arg.
{ 1 , 1 , 1 , 2 , 2 , 2 , 2 } ;
StringRef name = Template . getName ( ) ;
for ( int k = 0 ; stls [ k ] ; k + + ) {
if ( name . equals ( stls [ k ] ) ) return values [ k ] ;
}
}
// Check in some struct if the Template decl is registered something like
/*
DefaultCollection : : const_iterator iter ;
iter = m_defaultArgs . find ( & Template ) ;
if ( iter ! = m_defaultArgs . end ( ) ) {
return iter - > second ;
}
*/
return 0 ;
}
2014-10-07 18:06:28 +04:00
static bool ShouldKeepTypedef ( const TypedefType * TT ,
const llvm : : SmallSet < const Decl * , 4 > & ToSkip )
2012-09-23 01:30:24 +04:00
{
// Return true, if we should keep this typedef rather than desugaring it.
2014-10-07 18:06:28 +04:00
return 0 ! = ToSkip . count ( TT - > getDecl ( ) - > getCanonicalDecl ( ) ) ;
2012-09-23 01:30:24 +04:00
}
2013-12-13 02:03:14 +04:00
static 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 : {
//const TemplateSpecializationType* Ty =
// llvm::cast<TemplateSpecializationType>(QTy);
2014-03-21 18:48:31 +04:00
// Too broad, this returns a the target template but with
// canonical argument types.
//if (Ty->isTypeAlias()) {
// QT = Ty->getAliasedType();
// return true;
//}
// Too broad, this returns the canonical type
2012-11-30 01:40:44 +04:00
//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 ) {
2013-12-05 19:21:12 +04:00
Qualifiers quals = QT . getQualifiers ( ) ;
2012-12-02 00:37:09 +04:00
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-12-05 19:21:12 +04:00
2015-10-28 20:19:19 +03:00
static bool GetPartiallyDesugaredTypeImpl ( const ASTContext & Ctx ,
TemplateArgument & arg ,
const Transform : : Config & TypeConfig ,
bool fullyQualifyTmpltArg ) {
bool changed = false ;
if ( arg . getKind ( ) = = TemplateArgument : : Template ) {
TemplateName tname = arg . getAsTemplate ( ) ;
// Note: should we not also desugar?
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.
if ( isa < TypedefType > ( SubTy )
| | isa < TemplateSpecializationType > ( SubTy )
| | isa < ElaboratedType > ( SubTy )
| | fullyQualifyTmpltArg ) {
changed = true ;
QualType PDQT
= GetPartiallyDesugaredTypeImpl ( Ctx , SubTy , TypeConfig ,
/*fullyQualifyType=*/ true ,
/*fullyQualifyTmpltArg=*/ true ) ;
arg = TemplateArgument ( PDQT ) ;
}
} else if ( arg . getKind ( ) = = TemplateArgument : : Pack ) {
SmallVector < TemplateArgument , 2 > desArgs ;
for ( auto I = arg . pack_begin ( ) , E = arg . pack_end ( ) ; I ! = E ; + + I ) {
TemplateArgument pack_arg ( * I ) ;
changed = GetPartiallyDesugaredTypeImpl ( Ctx , pack_arg ,
TypeConfig ,
fullyQualifyTmpltArg ) ;
desArgs . push_back ( pack_arg ) ;
}
if ( changed ) {
// The allocator in ASTContext is mutable ...
// Keep the argument const to be inline will all the other interfaces
// like: NestedNameSpecifier::Create
ASTContext & mutableCtx ( const_cast < ASTContext & > ( Ctx ) ) ;
2016-06-15 12:31:15 +03:00
arg = TemplateArgument : : CreatePackCopy ( mutableCtx , desArgs ) ;
2015-10-28 20:19:19 +03:00
}
}
return changed ;
}
2015-12-23 00:19:05 +03:00
static const TemplateArgument *
GetTmpltArgDeepFirstIndexPack ( size_t & cur ,
const TemplateArgument & arg ,
size_t idx ) {
SmallVector < TemplateArgument , 2 > desArgs ;
for ( auto I = arg . pack_begin ( ) , E = arg . pack_end ( ) ;
cur < idx & & I ! = E ; + + cur , + + I ) {
if ( ( * I ) . getKind ( ) = = TemplateArgument : : Pack ) {
auto p_arg = GetTmpltArgDeepFirstIndexPack ( cur , ( * I ) , idx ) ;
if ( cur = = idx ) return p_arg ;
} else if ( cur = = idx ) {
return I ;
}
}
return nullptr ;
}
2015-10-28 20:19:19 +03:00
2015-12-23 00:19:05 +03:00
// Return the template argument corresponding to the index (idx)
// when the composite list of arguement is seen flattened out deep
// first (where depth is provided by template argument packs)
static const TemplateArgument *
GetTmpltArgDeepFirstIndex ( const TemplateArgumentList & templateArgs ,
size_t idx ) {
for ( size_t cur = 0 , I = 0 , E = templateArgs . size ( ) ;
cur < = idx & & I < E ; + + I , + + cur ) {
auto & arg = templateArgs [ I ] ;
if ( arg . getKind ( ) = = TemplateArgument : : Pack ) {
// Need to recurse.
auto p_arg = GetTmpltArgDeepFirstIndexPack ( cur , arg , idx ) ;
if ( cur = = idx ) return p_arg ;
} else if ( cur = = idx ) {
return & arg ;
}
}
return nullptr ;
}
2015-10-28 20:19:19 +03:00
2013-12-05 19:21:12 +04:00
static QualType GetPartiallyDesugaredTypeImpl ( const ASTContext & Ctx ,
2013-09-03 08:44:24 +04:00
QualType QT , const Transform : : Config & TypeConfig ,
2013-12-05 19:21:12 +04:00
bool fullyQualifyType , bool fullyQualifyTmpltArg )
2012-11-30 01:40:44 +04:00
{
2013-12-02 12:49:39 +04:00
if ( QT . isNull ( ) )
return QT ;
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.
2013-12-05 19:21:12 +04:00
Qualifiers quals = QT . getQualifiers ( ) ;
2014-05-14 10:11:41 +04:00
QualType nQT ;
nQT = GetPartiallyDesugaredTypeImpl ( Ctx , QT - > getPointeeType ( ) , TypeConfig ,
fullyQualifyType , fullyQualifyTmpltArg ) ;
if ( nQT = = QT - > getPointeeType ( ) ) return QT ;
QT = Ctx . getPointerType ( nQT ) ;
2012-09-05 13:37:39 +04:00
// 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-12-05 19:21:12 +04:00
2013-02-12 22:38:58 +04:00
while ( isa < SubstTemplateTypeParmType > ( QT . getTypePtr ( ) ) ) {
// Get the qualifiers.
2013-12-05 19:21:12 +04:00
Qualifiers quals = QT . getQualifiers ( ) ;
2013-02-12 22:38:58 +04:00
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
2014-05-14 06:01:01 +04:00
// the reference 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 ( ) ;
2014-05-14 10:11:41 +04:00
QualType nQT ;
nQT = GetPartiallyDesugaredTypeImpl ( Ctx , QT - > getPointeeType ( ) , TypeConfig ,
2013-08-29 02:02:57 +04:00
fullyQualifyType , fullyQualifyTmpltArg ) ;
2014-05-14 10:11:41 +04:00
if ( nQT = = QT - > getPointeeType ( ) ) return QT ;
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 )
2014-05-14 10:11:41 +04:00
QT = Ctx . getLValueReferenceType ( nQT ) ;
2012-09-05 13:37:39 +04:00
else
2014-05-14 10:11:41 +04:00
QT = Ctx . getRValueReferenceType ( nQT ) ;
2012-09-05 13:37:39 +04:00
// Add back the qualifiers.
QT = Ctx . getQualifiedType ( QT , quals ) ;
2012-09-23 01:30:24 +04:00
return QT ;
}
2014-05-14 06:01:01 +04:00
// In case of Int_t[2] we need to strip the array first, desugar and attach
// the array once again.
if ( isa < ArrayType > ( QT . getTypePtr ( ) ) ) {
// Get the qualifiers.
Qualifiers quals = QT . getQualifiers ( ) ;
if ( isa < ConstantArrayType > ( QT . getTypePtr ( ) ) ) {
const ConstantArrayType * arr
= dyn_cast < ConstantArrayType > ( QT . getTypePtr ( ) ) ;
QualType newQT
= GetPartiallyDesugaredTypeImpl ( Ctx , arr - > getElementType ( ) , TypeConfig ,
fullyQualifyType , fullyQualifyTmpltArg ) ;
2014-05-14 10:11:41 +04:00
if ( newQT = = arr - > getElementType ( ) ) return QT ;
2014-05-14 06:01:01 +04:00
QT = Ctx . getConstantArrayType ( newQT ,
arr - > getSize ( ) ,
arr - > getSizeModifier ( ) ,
arr - > getIndexTypeCVRQualifiers ( ) ) ;
} else if ( isa < DependentSizedArrayType > ( QT . getTypePtr ( ) ) ) {
const DependentSizedArrayType * arr
= dyn_cast < DependentSizedArrayType > ( QT . getTypePtr ( ) ) ;
QualType newQT
= GetPartiallyDesugaredTypeImpl ( Ctx , arr - > getElementType ( ) , TypeConfig ,
fullyQualifyType , fullyQualifyTmpltArg ) ;
if ( newQT = = QT ) return QT ;
QT = Ctx . getDependentSizedArrayType ( newQT ,
arr - > getSizeExpr ( ) ,
arr - > getSizeModifier ( ) ,
arr - > getIndexTypeCVRQualifiers ( ) ,
arr - > getBracketsRange ( ) ) ;
} else if ( isa < IncompleteArrayType > ( QT . getTypePtr ( ) ) ) {
const IncompleteArrayType * arr
= dyn_cast < IncompleteArrayType > ( QT . getTypePtr ( ) ) ;
QualType newQT
= GetPartiallyDesugaredTypeImpl ( Ctx , arr - > getElementType ( ) , TypeConfig ,
fullyQualifyType , fullyQualifyTmpltArg ) ;
2014-05-14 10:11:41 +04:00
if ( newQT = = arr - > getElementType ( ) ) return QT ;
2014-05-14 06:01:01 +04:00
QT = Ctx . getIncompleteArrayType ( newQT ,
arr - > getSizeModifier ( ) ,
arr - > getIndexTypeCVRQualifiers ( ) ) ;
} else if ( isa < VariableArrayType > ( QT . getTypePtr ( ) ) ) {
const VariableArrayType * arr
= dyn_cast < VariableArrayType > ( QT . getTypePtr ( ) ) ;
QualType newQT
= GetPartiallyDesugaredTypeImpl ( Ctx , arr - > getElementType ( ) , TypeConfig ,
fullyQualifyType , fullyQualifyTmpltArg ) ;
2014-05-14 10:11:41 +04:00
if ( newQT = = arr - > getElementType ( ) ) return QT ;
2014-05-14 06:01:01 +04:00
QT = Ctx . getVariableArrayType ( newQT ,
arr - > getSizeExpr ( ) ,
arr - > getSizeModifier ( ) ,
arr - > getIndexTypeCVRQualifiers ( ) ,
arr - > getBracketsRange ( ) ) ;
}
// Add back the qualifiers.
QT = Ctx . getQualifiedType ( QT , quals ) ;
return QT ;
}
2012-09-23 01:30:24 +04:00
// If the type is elaborated, first remove the prefix and then
// when we are done we will as needed add back the (new) prefix.
2013-12-05 19:21:12 +04:00
// for example for std::vector<int>::iterator, we work on
2012-09-23 01:30:24 +04:00
// 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 ;
2013-12-05 19:21:12 +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 ) {
2014-10-07 18:06:28 +04:00
if ( const TypedefType * TT = llvm : : dyn_cast < TypedefType > ( QT . getTypePtr ( ) ) ) {
if ( ShouldKeepTypedef ( TT , TypeConfig . m_toSkip ) ) {
if ( ! fullyQualifyType & & ! fullyQualifyTmpltArg ) {
return QT ;
}
// We might have stripped the namespace/scope part,
// so we must go on to add it back.
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
2015-05-08 19:53:42 +03:00
iter = TypeConfig . m_toReplace . find ( QT - > getCanonicalTypeInternal ( ) . getTypePtr ( ) ) ;
2013-09-03 08:44:24 +04:00
if ( iter ! = TypeConfig . m_toReplace . end ( ) ) {
Qualifiers quals = QT . getQualifiers ( ) ;
2013-12-04 19:39:43 +04:00
QT = QualType ( iter - > second , 0 ) ;
2013-09-03 08:44:24 +04:00
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
2014-05-14 06:01:01 +04:00
// If we have a reference, array or pointer we still need to
2012-10-19 17:24:46 +04:00
// desugar what they point to.
2013-03-01 21:59:59 +04:00
if ( isa < PointerType > ( QT . getTypePtr ( ) ) | |
2014-05-14 06:01:01 +04:00
isa < ReferenceType > ( QT . getTypePtr ( ) ) | |
isa < ArrayType > ( QT . getTypePtr ( ) ) ) {
2013-12-05 19:21:12 +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 ;
2013-12-05 19:21:12 +04:00
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 ) ;
2013-12-05 19:21:12 +04:00
2012-09-25 23:35:24 +04:00
prefix_qualifiers . addQualifiers ( QT . getLocalQualifiers ( ) ) ;
QT = QualType ( etype - > getNamedType ( ) . getTypePtr ( ) , 0 ) ;
2013-12-05 19:21:12 +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 ;
2013-12-05 19:21:12 +04:00
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 ...
2013-12-05 19:21:12 +04:00
const TagType * tagdecltype = 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 ) {
2013-12-05 19:21:12 +04:00
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 ( ) )
2014-08-29 17:22:15 +04:00
& & ! outer - > getNameAsString ( ) . empty ( ) ) {
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-12-05 19:21:12 +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 ( ) ;
}
2013-12-05 19:21:12 +04:00
else if ( NamespaceAliasDecl * alias =
2012-09-26 12:01:21 +04:00
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)
2013-12-05 19:21:12 +04:00
// move qualifiers on the outer type (avoid 'std::const string'!)
2012-09-26 12:01:21 +04:00
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 ( ) ) {
2013-12-04 19:39:43 +04:00
prefix = TypeName : : 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 ) {
2013-12-04 21:26:23 +04:00
prefix = TypeName : : CreateNestedNameSpecifier ( Ctx , tdecl ,
false /*FullyQualified*/ ) ;
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
}
}
2013-12-05 19:21:12 +04:00
// In case of template specializations iterate over the arguments and
2012-09-05 13:37:39 +04:00
// desugar them as well.
2013-12-05 19:21:12 +04:00
if ( const TemplateSpecializationType * TST
2012-09-05 13:37:39 +04:00
= dyn_cast < const TemplateSpecializationType > ( QT . getTypePtr ( ) ) ) {
2013-12-05 19:21:12 +04:00
2014-03-21 18:48:31 +04:00
if ( TST - > isTypeAlias ( ) ) {
QualType targetType = TST - > getAliasedType ( ) ;
/*
// We really need to find a way to propagate/keep the opaque typedef
// that are available in TST to the aliased type. We would need
// to do something like:
QualType targetType = TST - > getAliasedType ( ) ;
QualType resubst = ReSubstTemplateArg ( targetType , TST ) ;
return GetPartiallyDesugaredTypeImpl ( Ctx , resubst , TypeConfig ,
fullyQualifyType ,
fullyQualifyTmpltArg ) ;
// But this is not quite right (ReSubstTemplateArg is from TMetaUtils)
// as it does not resubst for
template < typename T > using myvector = std : : vector < T > ;
myvector < Double32_t > vd32d ;
// and does not work at all for
template < class T > using ptr = T * ;
ptr < Double32_t > p2 ;
2014-08-04 06:05:42 +04:00
2014-03-21 18:48:31 +04:00
// as the target is not a template.
*/
// So for now just return move on with the least lose we can do
return GetPartiallyDesugaredTypeImpl ( Ctx , targetType , TypeConfig ,
fullyQualifyType ,
fullyQualifyTmpltArg ) ;
}
2012-09-05 13:37:39 +04:00
bool mightHaveChanged = false ;
llvm : : SmallVector < TemplateArgument , 4 > desArgs ;
2013-10-30 16:23:58 +04:00
unsigned int argi = 0 ;
2012-09-05 13:37:39 +04:00
for ( TemplateSpecializationType : : iterator I = TST - > begin ( ) , E = TST - > end ( ) ;
2013-10-30 16:23:58 +04:00
I ! = E ; + + I , + + argi ) {
2014-09-17 22:37:11 +04:00
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 ( ) ;
mightHaveChanged = true ;
2015-12-23 00:19:05 +03:00
const TemplateArgument * match
= GetTmpltArgDeepFirstIndex ( templateArgs , argi ) ;
if ( match ) desArgs . push_back ( * match ) ;
2014-09-17 22:37:11 +04:00
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 ;
}
2013-10-30 16:23:58 +04:00
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.
2013-12-05 19:21:12 +04:00
if ( isa < TypedefType > ( SubTy )
2012-09-05 13:37:39 +04:00
| | isa < TemplateSpecializationType > ( SubTy )
2012-09-25 23:35:24 +04:00
| | isa < ElaboratedType > ( SubTy )
2013-08-29 02:02:57 +04:00
| | fullyQualifyTmpltArg ) {
2013-12-05 19:21:12 +04:00
QualType PDQT
= GetPartiallyDesugaredTypeImpl ( Ctx , SubTy , TypeConfig ,
fullyQualifyType ,
fullyQualifyTmpltArg ) ;
2014-09-02 16:33:06 +04:00
mightHaveChanged | = ( SubTy ! = PDQT ) ;
2013-12-05 19:21:12 +04:00
desArgs . push_back ( TemplateArgument ( PDQT ) ) ;
} else {
2012-09-05 13:37:39 +04:00
desArgs . push_back ( * I ) ;
2013-12-05 19:21:12 +04:00
}
2012-09-05 13:37:39 +04:00
}
2013-12-05 19:21:12 +04:00
2012-09-05 13:37:39 +04:00
// If desugaring happened allocate new type in the AST.
if ( mightHaveChanged ) {
2012-09-26 12:01:21 +04:00
Qualifiers qualifiers = QT . getLocalQualifiers ( ) ;
2013-12-05 19:21:12 +04:00
QT = Ctx . getTemplateSpecializationType ( TST - > getTemplateName ( ) ,
2017-05-18 16:16:30 +03:00
desArgs ,
2012-09-19 16:39:06 +04:00
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-12-05 19:21:12 +04:00
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.
2013-12-05 19:21:12 +04:00
2013-02-08 02:56:10 +04:00
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 ) {
2013-10-30 16:23:58 +04:00
2015-10-28 20:19:19 +03:00
# if 1
2014-09-17 22:37:11 +04:00
// cheap to copy and potentially modified by
2015-10-28 20:19:19 +03:00
// GetPartiallyDesugaredTypeImpl
TemplateArgument arg ( templateArgs [ I ] ) ;
mightHaveChanged | = GetPartiallyDesugaredTypeImpl ( Ctx , arg ,
TypeConfig ,
fullyQualifyTmpltArg ) ;
2014-09-17 22:37:11 +04:00
desArgs . push_back ( arg ) ;
2015-10-28 20:19:19 +03:00
# else
2014-09-17 22:37:11 +04:00
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 ;
}
2013-02-08 02:56:10 +04:00
if ( templateArgs [ I ] . getKind ( ) ! = TemplateArgument : : Type ) {
desArgs . push_back ( templateArgs [ I ] ) ;
continue ;
}
2013-12-05 19:21:12 +04:00
2013-02-08 02:56:10 +04:00
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-12-05 19:21:12 +04:00
QualType PDQT
= GetPartiallyDesugaredTypeImpl ( Ctx , SubTy , TypeConfig ,
/*fullyQualifyType=*/ true ,
/*fullyQualifyTmpltArg=*/ true ) ;
desArgs . push_back ( TemplateArgument ( PDQT ) ) ;
} else {
2013-02-08 02:56:10 +04:00
desArgs . push_back ( templateArgs [ I ] ) ;
2013-12-05 19:21:12 +04:00
}
2015-10-28 20:19:19 +03:00
# endif
2013-02-08 02:56:10 +04:00
}
2013-12-05 19:21:12 +04:00
2013-02-08 02:56:10 +04:00
// If desugaring happened allocate new type in the AST.
if ( mightHaveChanged ) {
Qualifiers qualifiers = QT . getLocalQualifiers ( ) ;
2013-12-05 19:21:12 +04:00
TemplateName TN ( TSTdecl - > getSpecializedTemplate ( ) ) ;
2017-05-18 16:16:30 +03:00
QT = Ctx . getTemplateSpecializationType ( TN , desArgs ,
2013-10-30 16:23:58 +04:00
TSTRecord - > getCanonicalTypeInternal ( ) ) ;
2013-02-08 02:56:10 +04:00
QT = Ctx . getQualifiedType ( QT , qualifiers ) ;
}
}
}
2012-09-05 13:37:39 +04:00
}
2014-09-02 16:33:06 +04:00
// TODO: Find a way to avoid creating new types, if the input is already
// fully qualified.
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 ) ;
2013-11-06 20:04:33 +04:00
} else if ( original_prefix ) {
2014-09-02 16:33:06 +04:00
QT = Ctx . getQualifiedType ( QT , prefix_qualifiers ) ;
2012-09-05 13:37:39 +04:00
}
2013-12-05 19:21:12 +04:00
return QT ;
2012-09-05 13:37:39 +04:00
}
2013-12-05 19:21:12 +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 ) ;
}
2013-12-05 19:21:12 +04:00
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 ) ;
2013-12-02 17:15:19 +04:00
R . suppressDiagnostics ( ) ;
2012-09-05 13:37:39 +04:00
if ( ! Within )
S - > LookupName ( R , S - > TUScope ) ;
2014-04-27 20:14:03 +04:00
else {
if ( const clang : : TagDecl * TD = dyn_cast < clang : : TagDecl > ( Within ) ) {
if ( ! TD - > getDefinition ( ) ) {
// No definition, no lookup result.
return 0 ;
}
}
2012-11-20 23:13:06 +04:00
S - > LookupQualifiedName ( R , const_cast < DeclContext * > ( Within ) ) ;
2014-04-27 20:14:03 +04:00
}
2012-09-05 13:37:39 +04:00
if ( R . empty ( ) )
return 0 ;
R . resolveKind ( ) ;
return dyn_cast < NamespaceDecl > ( R . getFoundDecl ( ) ) ;
}
2014-09-15 14:14:40 +04:00
NamedDecl * Lookup : : Named ( Sema * S , llvm : : StringRef Name ,
const DeclContext * Within ) {
2018-02-17 00:11:46 +03:00
DeclarationName DName = & S - > Context . Idents . get ( Name ) ;
return Lookup : : Named ( S , DName , Within ) ;
2014-09-15 14:14:40 +04:00
}
2012-11-20 23:13:06 +04:00
NamedDecl * Lookup : : Named ( Sema * S , const char * Name ,
const DeclContext * Within ) {
2018-02-17 00:11:46 +03:00
return Lookup : : Named ( S , llvm : : StringRef ( Name ) , Within ) ;
2012-10-09 13:41:26 +04:00
}
2012-09-05 13:37:39 +04:00
2017-12-05 11:35:13 +03:00
NamedDecl * Lookup : : Named ( Sema * S , const clang : : 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 ) ;
2017-12-05 11:35:13 +03:00
Lookup : : Named ( S , R , Within ) ;
2018-09-03 16:42:02 +03:00
return LookupResult2Decl < clang : : NamedDecl > ( R ) ;
}
2017-12-05 11:35:13 +03:00
2018-09-03 16:42:02 +03:00
TagDecl * Lookup : : Tag ( Sema * S , llvm : : StringRef Name ,
2018-09-21 14:16:09 +03:00
const DeclContext * Within ) {
2018-09-03 16:42:02 +03:00
DeclarationName DName = & S - > Context . Idents . get ( Name ) ;
return Lookup : : Tag ( S , DName , Within ) ;
}
2017-12-05 11:35:13 +03:00
2018-09-03 16:42:02 +03:00
TagDecl * Lookup : : Tag ( Sema * S , const char * Name ,
2018-09-21 14:16:09 +03:00
const DeclContext * Within ) {
2018-09-03 16:42:02 +03:00
return Lookup : : Tag ( S , llvm : : StringRef ( Name ) , Within ) ;
}
TagDecl * Lookup : : Tag ( Sema * S , const clang : : DeclarationName & Name ,
2018-09-21 14:16:09 +03:00
const DeclContext * Within ) {
2018-09-03 16:42:02 +03:00
LookupResult R ( * S , Name , SourceLocation ( ) , Sema : : LookupTagName ,
Sema : : ForRedeclaration ) ;
Lookup : : Named ( S , R , Within ) ;
return LookupResult2Decl < clang : : TagDecl > ( R ) ;
2017-12-05 11:35:13 +03:00
}
void Lookup : : Named ( Sema * S , LookupResult & R , const DeclContext * Within ) {
2013-12-02 17:15:19 +04:00
R . suppressDiagnostics ( ) ;
2012-09-05 13:37:39 +04:00
if ( ! Within )
S - > LookupName ( R , S - > TUScope ) ;
2014-04-27 20:14:03 +04:00
else {
2015-10-15 23:39:45 +03:00
const DeclContext * primaryWithin = nullptr ;
if ( const clang : : TagDecl * TD = dyn_cast < clang : : TagDecl > ( Within ) ) {
primaryWithin = dyn_cast_or_null < DeclContext > ( TD - > getDefinition ( ) ) ;
} else {
primaryWithin = Within - > getPrimaryContext ( ) ;
}
2015-10-15 22:27:07 +03:00
if ( ! primaryWithin ) {
// No definition, no lookup result.
2017-12-05 11:35:13 +03:00
return ;
2014-04-27 20:14:03 +04:00
}
2015-10-15 22:27:07 +03:00
S - > LookupQualifiedName ( R , const_cast < DeclContext * > ( primaryWithin ) ) ;
2014-04-27 20:14:03 +04:00
}
2012-09-05 13:37:39 +04:00
}
2013-12-04 19:39:43 +04:00
static NestedNameSpecifier *
CreateNestedNameSpecifierForScopeOf ( const ASTContext & Ctx ,
2014-09-17 22:37:11 +04:00
const Decl * decl ,
2013-12-04 21:26:23 +04:00
bool FullyQualified )
2013-12-04 19:39:43 +04:00
{
// Create a nested name specifier for the declaring context of the type.
2014-09-17 22:37:11 +04:00
assert ( decl ) ;
2013-12-04 19:39:43 +04:00
2014-09-17 22:37:11 +04:00
const NamedDecl * outer
2013-12-04 19:39:43 +04:00
= llvm : : dyn_cast_or_null < NamedDecl > ( decl - > getDeclContext ( ) ) ;
2014-09-17 22:37:11 +04:00
const NamespaceDecl * outer_ns
2013-12-04 19:39:43 +04:00
= llvm : : dyn_cast_or_null < NamespaceDecl > ( decl - > getDeclContext ( ) ) ;
if ( outer & & ! ( outer_ns & & outer_ns - > isAnonymousNamespace ( ) ) ) {
2013-12-05 19:21:12 +04:00
2014-09-17 22:37:11 +04:00
if ( const CXXRecordDecl * cxxdecl
2013-12-04 19:39:43 +04:00
= llvm : : dyn_cast < CXXRecordDecl > ( decl - > getDeclContext ( ) ) ) {
2013-12-05 19:21:12 +04:00
2013-12-04 19:39:43 +04:00
if ( ClassTemplateDecl * clTempl = cxxdecl - > getDescribedClassTemplate ( ) ) {
// We are in the case of a type(def) that was declared in a
// class template but is *not* type dependent. In clang, it gets
// attached to the class template declaration rather than any
// specific class template instantiation. This result in 'odd'
// fully qualified typename:
// vector<_Tp,_Alloc>::size_type
// Make the situation is 'useable' but looking a bit odd by
// picking a random instance as the declaring context.
2018-11-15 12:14:38 +03:00
// FIXME: We should not use the iterators here to check if we are in
// a template specialization. clTempl != cxxdecl already tell us that
// is the case. It seems that we rely on a side-effect from triggering
// deserializations to support 'some' use-case. See ROOT-9709.
2013-12-04 19:39:43 +04:00
if ( clTempl - > spec_begin ( ) ! = clTempl - > spec_end ( ) ) {
decl = * ( clTempl - > spec_begin ( ) ) ;
outer = llvm : : dyn_cast < NamedDecl > ( decl ) ;
outer_ns = llvm : : dyn_cast < NamespaceDecl > ( decl ) ;
}
}
}
if ( outer_ns ) {
return TypeName : : CreateNestedNameSpecifier ( Ctx , outer_ns ) ;
2014-01-20 17:37:13 +04:00
} else if ( const TagDecl * TD = llvm : : dyn_cast < TagDecl > ( outer ) ) {
return TypeName : : CreateNestedNameSpecifier ( Ctx , TD , FullyQualified ) ;
2013-12-04 19:39:43 +04:00
}
}
return 0 ;
}
2014-09-17 22:37:11 +04:00
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 ) ;
}
2013-12-04 19:39:43 +04:00
NestedNameSpecifier *
TypeName : : CreateNestedNameSpecifier ( const ASTContext & Ctx ,
const NamespaceDecl * Namesp ) {
2014-01-12 19:59:12 +04:00
while ( Namesp & & Namesp - > isInline ( ) ) {
// Ignore inline namespace;
Namesp = dyn_cast_or_null < NamespaceDecl > ( Namesp - > getDeclContext ( ) ) ;
}
if ( ! Namesp ) return 0 ;
2013-12-04 21:26:23 +04:00
bool FullyQualified = true ; // doesn't matter, DeclContexts are namespaces
return NestedNameSpecifier : : Create ( Ctx , CreateOuterNNS ( Ctx , Namesp ,
FullyQualified ) ,
Namesp ) ;
2013-12-04 19:39:43 +04:00
}
2013-12-05 19:21:12 +04:00
2014-01-06 21:04:47 +04:00
NestedNameSpecifier *
TypeName : : CreateNestedNameSpecifier ( const ASTContext & Ctx ,
const TypedefNameDecl * TD ,
bool FullyQualify ) {
return NestedNameSpecifier : : Create ( Ctx , CreateOuterNNS ( Ctx , TD ,
FullyQualify ) ,
true /*Template*/ ,
TD - > getTypeForDecl ( ) ) ;
}
2013-12-04 19:39:43 +04:00
NestedNameSpecifier *
TypeName : : CreateNestedNameSpecifier ( const ASTContext & Ctx ,
2013-12-04 21:26:23 +04:00
const TagDecl * TD , bool FullyQualify ) {
const Type * Ty
= Ctx . getTypeDeclType ( TD ) . getTypePtr ( ) ;
if ( FullyQualify )
Ty = GetFullyQualifiedLocalType ( Ctx , Ty ) ;
return NestedNameSpecifier : : Create ( Ctx ,
CreateOuterNNS ( Ctx , TD , FullyQualify ) ,
2013-12-04 19:39:43 +04:00
false /* template keyword wanted */ ,
2013-12-04 21:26:23 +04:00
Ty ) ;
2013-12-04 19:39:43 +04:00
}
2013-12-05 19:21:12 +04:00
2013-12-04 19:39:43 +04:00
QualType
TypeName : : GetFullyQualifiedType ( QualType QT , const ASTContext & Ctx ) {
// Return the fully qualified type, if we need to recurse through any
// template parameter, this needs to be merged somehow with
// GetPartialDesugaredType.
// In case of myType* we need to strip the pointer first, fully qualifiy
// and attach the pointer once again.
if ( llvm : : isa < PointerType > ( QT . getTypePtr ( ) ) ) {
// Get the qualifiers.
Qualifiers quals = QT . getQualifiers ( ) ;
QT = GetFullyQualifiedType ( QT - > getPointeeType ( ) , Ctx ) ;
QT = Ctx . getPointerType ( QT ) ;
// Add back the qualifiers.
QT = Ctx . getQualifiedType ( QT , quals ) ;
return QT ;
}
// In case of myType& we need to strip the pointer first, fully qualifiy
// and attach the pointer once again.
if ( llvm : : isa < ReferenceType > ( QT . getTypePtr ( ) ) ) {
// Get the qualifiers.
bool isLValueRefTy = llvm : : isa < LValueReferenceType > ( QT . getTypePtr ( ) ) ;
Qualifiers quals = QT . getQualifiers ( ) ;
QT = GetFullyQualifiedType ( QT - > getPointeeType ( ) , Ctx ) ;
// Add the r- or l-value reference type back to the desugared one.
if ( isLValueRefTy )
QT = Ctx . getLValueReferenceType ( QT ) ;
else
QT = Ctx . getRValueReferenceType ( QT ) ;
// Add back the qualifiers.
QT = Ctx . getQualifiedType ( QT , quals ) ;
return QT ;
}
2018-03-25 22:09:47 +03:00
// Strip deduced types.
if ( const AutoType * AutoTy = dyn_cast < AutoType > ( QT . getTypePtr ( ) ) ) {
if ( ! AutoTy - > getDeducedType ( ) . isNull ( ) )
return GetFullyQualifiedType ( AutoTy - > getDeducedType ( ) , Ctx ) ;
}
2015-10-02 13:53:49 +03:00
// Remove the part of the type related to the type being a template
// parameter (we won't report it as part of the 'type name' and it is
// actually make the code below to be more complex (to handle those)
while ( isa < SubstTemplateTypeParmType > ( QT . getTypePtr ( ) ) ) {
// Get the qualifiers.
Qualifiers quals = QT . getQualifiers ( ) ;
QT = dyn_cast < SubstTemplateTypeParmType > ( QT . getTypePtr ( ) ) - > desugar ( ) ;
// Add back the qualifiers.
QT = Ctx . getQualifiedType ( QT , quals ) ;
}
2013-12-04 19:39:43 +04:00
NestedNameSpecifier * prefix = 0 ;
Qualifiers prefix_qualifiers ;
if ( const ElaboratedType * etype_input
= llvm : : dyn_cast < ElaboratedType > ( QT . getTypePtr ( ) ) ) {
// Intentionally, we do not care about the other compononent of
// the elaborated type (the keyword) as part of the partial
// desugaring (and/or name normalization) is to remove it.
prefix = etype_input - > getQualifier ( ) ;
if ( prefix ) {
const NamespaceDecl * ns = prefix - > getAsNamespace ( ) ;
2013-12-21 18:06:08 +04:00
if ( prefix ! = NestedNameSpecifier : : GlobalSpecifier ( Ctx )
& & ! ( ns & & ns - > isAnonymousNamespace ( ) ) ) {
2013-12-04 19:39:43 +04:00
prefix_qualifiers = QT . getLocalQualifiers ( ) ;
2013-12-20 18:16:50 +04:00
prefix = GetFullyQualifiedNameSpecifier ( Ctx , prefix ) ;
2013-12-04 19:39:43 +04:00
QT = QualType ( etype_input - > getNamedType ( ) . getTypePtr ( ) , 0 ) ;
} else {
prefix = 0 ;
}
}
} else {
// Create a nested name specifier if needed (i.e. if the decl context
// is not the global scope.
2013-12-04 21:26:23 +04:00
prefix = CreateNestedNameSpecifierForScopeOf ( Ctx , QT . getTypePtr ( ) ,
true /*FullyQualified*/ ) ;
2013-12-04 19:39:43 +04:00
// move the qualifiers on the outer type (avoid 'std::const string'!)
if ( prefix ) {
prefix_qualifiers = QT . getLocalQualifiers ( ) ;
QT = QualType ( QT . getTypePtr ( ) , 0 ) ;
}
}
// In case of template specializations iterate over the arguments and
// fully qualify them as well.
if ( llvm : : isa < const TemplateSpecializationType > ( QT . getTypePtr ( ) ) ) {
Qualifiers qualifiers = QT . getLocalQualifiers ( ) ;
const Type * TypePtr = GetFullyQualifiedLocalType ( Ctx , QT . getTypePtr ( ) ) ;
QT = Ctx . getQualifiedType ( TypePtr , qualifiers ) ;
} else if ( llvm : : isa < 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.
Qualifiers qualifiers = QT . getLocalQualifiers ( ) ;
const Type * TypePtr = GetFullyQualifiedLocalType ( Ctx , QT . getTypePtr ( ) ) ;
QT = Ctx . getQualifiedType ( TypePtr , qualifiers ) ;
}
if ( prefix ) {
// We intentionally always use ETK_None, we never want
// the keyword (humm ... what about anonymous types?)
QT = Ctx . getElaboratedType ( ETK_None , prefix , QT ) ;
QT = Ctx . getQualifiedType ( QT , prefix_qualifiers ) ;
}
2013-12-05 19:21:12 +04:00
return QT ;
2013-12-04 19:39:43 +04:00
}
2013-12-05 19:21:12 +04:00
std : : string TypeName : : GetFullyQualifiedName ( QualType QT ,
const ASTContext & Ctx ) {
2013-12-04 19:39:43 +04:00
QualType FQQT = GetFullyQualifiedType ( QT , Ctx ) ;
2013-12-05 19:21:12 +04:00
PrintingPolicy Policy ( Ctx . getPrintingPolicy ( ) ) ;
2013-12-04 19:39:43 +04:00
Policy . SuppressScope = false ;
Policy . AnonymousTagLocations = false ;
return FQQT . getAsString ( Policy ) ;
}
2012-09-05 13:37:39 +04:00
} // end namespace utils
} // end namespace cling