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"
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"
2012-10-15 20:57:53 +04:00
2012-09-05 13:37:39 +04:00
using namespace clang ;
namespace cling {
namespace utils {
2012-10-15 20:57:53 +04:00
2012-10-17 12:52:24 +04:00
bool Analyze : : IsWrapper ( const NamedDecl * ND ) {
if ( ! ND )
return false ;
return llvm : : StringRef ( ND - > getNameAsString ( ) )
. startswith ( Synthesize : : UniquePrefix ) ;
}
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 ( ) ) ) {
llvm : : ArrayRef < Stmt * > Stmts
= 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 " ;
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 ) {
ASTContext & Ctx = S - > getASTContext ( ) ;
if ( ! Ty - > isPointerType ( ) )
Ty = Ctx . getPointerType ( Ty ) ;
TypeSourceInfo * TSI = Ctx . CreateTypeSourceInfo ( Ty ) ;
2012-11-21 21:05:10 +04:00
Expr * Result = Synthesize : : IntegerLiteralExpr ( Ctx , Ptr ) ;
2012-09-05 13:37:39 +04:00
Result = S - > BuildCStyleCastExpr ( SourceLocation ( ) , TSI , SourceLocation ( ) ,
2012-11-21 21:05:10 +04:00
Result ) . 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-09-05 13:37:39 +04:00
static
NestedNameSpecifier * GetPartiallyDesugaredNNS ( const ASTContext & Ctx ,
NestedNameSpecifier * scope ,
const llvm : : SmallSet < const Type * , 4 > & TypesToSkip ) {
// Desugar the scope qualifier if needed.
const Type * scope_type = scope - > getAsType ( ) ;
if ( scope_type ) {
// this is not a namespace, so we might need to desugar
NestedNameSpecifier * outer_scope = scope - > getPrefix ( ) ;
if ( outer_scope ) {
outer_scope = GetPartiallyDesugaredNNS ( Ctx , outer_scope , TypesToSkip ) ;
}
QualType desugared =
Transform : : GetPartiallyDesugaredType ( Ctx ,
QualType ( scope_type , 0 ) ,
TypesToSkip ,
/*fullyQualify=*/ false ) ;
// NOTE: Should check whether the type has changed or not.
return NestedNameSpecifier : : Create ( Ctx , outer_scope ,
false /* template keyword wanted */ ,
desugared . getTypePtr ( ) ) ;
}
return scope ;
}
static
NestedNameSpecifier * CreateNestedNameSpecifier ( const ASTContext & Ctx ,
NamespaceDecl * cl ) {
NamespaceDecl * outer
= llvm : : dyn_cast_or_null < NamespaceDecl > ( cl - > getDeclContext ( ) ) ;
if ( outer & & outer - > getName ( ) . size ( ) ) {
NestedNameSpecifier * outerNNS = CreateNestedNameSpecifier ( Ctx , outer ) ;
return NestedNameSpecifier : : Create ( Ctx , outerNNS ,
cl ) ;
} else {
return NestedNameSpecifier : : Create ( Ctx ,
0 , /* no starting '::'*/
cl ) ;
}
}
static
NestedNameSpecifier * CreateNestedNameSpecifier ( const ASTContext & Ctx ,
TagDecl * cl ) {
NamedDecl * outer = llvm : : dyn_cast_or_null < NamedDecl > ( cl - > getDeclContext ( ) ) ;
if ( outer & & outer - > getName ( ) . size ( ) ) {
NestedNameSpecifier * outerNNS ;
if ( cl - > getDeclContext ( ) - > isNamespace ( ) ) {
outerNNS = CreateNestedNameSpecifier ( Ctx ,
llvm : : dyn_cast < NamespaceDecl > ( outer ) ) ;
} else {
outerNNS = CreateNestedNameSpecifier ( Ctx ,
llvm : : dyn_cast < TagDecl > ( outer ) ) ;
}
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 ( ) ) ;
}
}
2012-09-23 01:30:24 +04:00
static bool ShouldKeepTypedef ( QualType QT ,
const llvm : : SmallSet < const Type * , 4 > & TypesToSkip )
{
// Return true, if we should keep this typedef rather than desugaring it.
if ( 0 ! = TypesToSkip . count ( QT . getTypePtr ( ) ) )
return true ;
const TypedefType * typedeftype =
llvm : : dyn_cast_or_null < clang : : TypedefType > ( QT . getTypePtr ( ) ) ;
const TypedefNameDecl * decl = typedeftype ? typedeftype - > getDecl ( ) : 0 ;
if ( decl ) {
const NamedDecl * outer
= llvm : : dyn_cast_or_null < NamedDecl > ( decl - > getDeclContext ( ) ) ;
while ( outer & & outer - > getName ( ) . size ( ) ) {
2012-11-07 09:31:03 +04:00
// NOTE: Net is being cast too widely, replace by a lookup.
2012-09-23 01:30:24 +04:00
if ( outer - > getName ( ) . compare ( " std " ) = = 0 ) {
return true ;
}
outer = llvm : : dyn_cast_or_null < NamedDecl > ( outer - > getDeclContext ( ) ) ;
}
}
return false ;
}
2012-11-30 01:40:44 +04:00
bool Transform : : SingleStepPartiallyDesugarType ( QualType & QT )
{
// 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 : {
return false ;
//const SubstTemplateTypeParmType* Ty =
// llvm::cast<SubstTemplateTypeParmType>(QTy);
//QT = Ty->desugar();
//return true;
}
case Type : : Elaborated : {
return false ;
//const ElaboratedType* Ty = llvm::cast<ElaboratedType>(QTy);
///QT = Ty->desugar();
///return true;
//return false;
}
//
// 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-09-05 13:37:39 +04:00
QualType Transform : : GetPartiallyDesugaredType ( const ASTContext & Ctx ,
2012-11-30 01:40:44 +04:00
QualType QT , const llvm : : SmallSet < const Type * , 4 > & TypesToSkip ,
bool fullyQualify /*=true*/ )
{
// If there are no constraints, then use the standard desugaring.
2012-09-19 16:39:06 +04:00
if ( ! TypesToSkip . size ( ) & & ! fullyQualify )
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 ( ) ;
QT = GetPartiallyDesugaredType ( Ctx , QT - > getPointeeType ( ) , TypesToSkip ,
fullyQualify ) ;
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
}
// 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 ( ) ;
QT = GetPartiallyDesugaredType ( Ctx , QT - > getPointeeType ( ) , TypesToSkip ,
fullyQualify ) ;
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 ;
2012-09-25 23:35:24 +04:00
clang : : Qualifiers prefix_qualifiers ;
2012-09-23 01:30:24 +04:00
const ElaboratedType * etype_input
= llvm : : dyn_cast < ElaboratedType > ( QT . getTypePtr ( ) ) ;
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).
fullyQualify = true ;
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 ( ) ) & &
ShouldKeepTypedef ( QT , TypesToSkip ) ) {
if ( ! fullyQualify ) {
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
}
bool wasDesugared = SingleStepPartiallyDesugarType ( QT ) ;
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.
if ( isa < PointerType > ( QT . getTypePtr ( ) ) | |
isa < ReferenceType > ( QT . getTypePtr ( ) ) ) {
return GetPartiallyDesugaredType ( Ctx , QT , TypesToSkip ,
fullyQualify ) ;
}
2012-09-05 13:37:39 +04:00
NestedNameSpecifier * prefix = 0 ;
const ElaboratedType * etype
= llvm : : dyn_cast < ElaboratedType > ( QT . getTypePtr ( ) ) ;
if ( etype ) {
// We have to also desugar the prefix.
2012-09-23 01:30:24 +04:00
prefix = etype - > getQualifier ( ) ;
if ( original_prefix ) {
// 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.
const clang : : Type * newtype = prefix - > getAsType ( ) ;
if ( newtype ) {
// Deal with a class
const clang : : Type * oldtype = original_prefix - > getAsType ( ) ;
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.
prefix = GetPartiallyDesugaredNNS ( Ctx , original_prefix , TypesToSkip ) ;
} else {
prefix = GetPartiallyDesugaredNNS ( Ctx , prefix , TypesToSkip ) ;
}
} else {
// Deal with namespace. This is mostly about dealing with
2012-09-23 01:56:36 +04:00
// namespace aliases (i.e. keeping the one the user used).
2012-09-23 01:30:24 +04:00
const NamespaceDecl * new_ns = prefix - > getAsNamespace ( ) ;
if ( new_ns ) {
new_ns = new_ns - > getCanonicalDecl ( ) ;
}
else if ( NamespaceAliasDecl * alias = prefix - > getAsNamespaceAlias ( ) )
{
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.
prefix = original_prefix ;
}
}
}
}
2012-09-25 23:35:24 +04:00
prefix_qualifiers . addQualifiers ( QT . getLocalQualifiers ( ) ) ;
QT = QualType ( etype - > getNamedType ( ) . getTypePtr ( ) , 0 ) ;
2012-09-05 13:37:39 +04:00
} else if ( fullyQualify ) {
// 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 =
llvm : : dyn_cast_or_null < clang : : TypedefType > ( QT . getTypePtr ( ) ) ;
if ( typedeftype ) {
decl = typedeftype - > getDecl ( ) ;
} else {
// There are probably other cases ...
const TagType * tagdecltype =
llvm : : dyn_cast_or_null < clang : : TagType > ( QT . getTypePtr ( ) ) ;
if ( tagdecltype ) {
decl = tagdecltype - > getDecl ( ) ;
} else {
decl = QT - > getAsCXXRecordDecl ( ) ;
}
}
if ( decl ) {
NamedDecl * outer
= llvm : : dyn_cast_or_null < NamedDecl > ( decl - > getDeclContext ( ) ) ;
2012-10-26 23:51:56 +04:00
NamespaceDecl * outer_ns
= llvm : : dyn_cast_or_null < NamespaceDecl > ( decl - > getDeclContext ( ) ) ;
if ( outer
& & ! ( outer_ns & & outer_ns - > isAnonymousNamespace ( ) )
& & outer - > getName ( ) . size ( ) ) {
2012-09-26 12:01:21 +04:00
if ( original_prefix ) {
const clang : : Type * oldtype = original_prefix - > getAsType ( ) ;
if ( oldtype ) {
if ( oldtype - > getAsCXXRecordDecl ( ) = = outer ) {
// Same type, use the original spelling
prefix = GetPartiallyDesugaredNNS ( Ctx , original_prefix , TypesToSkip ) ;
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 ( ) ;
}
const NamespaceDecl * new_ns = llvm : : dyn_cast < NamespaceDecl > ( outer ) ;
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.
prefix = original_prefix ;
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 ,
2012-09-05 13:37:39 +04:00
llvm : : 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.
TagDecl * tdecl = llvm : : dyn_cast < TagDecl > ( outer ) ;
2012-12-01 22:02:54 +04:00
if ( tdecl ) {
prefix = CreateNestedNameSpecifier ( Ctx , tdecl ) ;
}
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 )
2012-09-05 13:37:39 +04:00
| | fullyQualify ) {
mightHaveChanged = true ;
desArgs . push_back ( TemplateArgument ( GetPartiallyDesugaredType ( Ctx ,
SubTy ,
TypesToSkip ,
fullyQualify ) ) ) ;
} else
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
}
}
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 ;
}
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