2012-09-05 13:37:39 +04:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id: AST.cpp 45014 2012-07-11 20:31:42Z vvassilev $
// author: Vassil Vassilev <vvasilev@cern.ch>
//------------------------------------------------------------------------------
# include "cling/Interpreter/LookupHelper.h"
2013-04-03 20:25:08 +04:00
# include "cling/Interpreter/Interpreter.h"
2012-09-05 13:37:39 +04:00
# include "clang/AST/ASTContext.h"
# include "clang/Parse/Parser.h"
2012-11-16 00:19:21 +04:00
# include "clang/Parse/RAIIObjectsForParser.h"
2012-09-05 13:37:39 +04:00
# include "clang/Sema/Scope.h"
# include "clang/Sema/Lookup.h"
# include "clang/Sema/Overload.h"
# include "clang/Sema/Sema.h"
# include "clang/Sema/Template.h"
# include "clang/Sema/TemplateDeduction.h"
using namespace clang ;
namespace cling {
///\brief Cleanup Parser state after a failed lookup.
2013-08-03 09:48:28 +04:00
///
2012-09-05 13:37:39 +04:00
/// After a failed lookup we need to discard the remaining unparsed input,
2012-11-20 17:17:55 +04:00
/// restore the original state of the incremental parsing flag, clear any
2012-09-05 13:37:39 +04:00
/// pending diagnostics, restore the suppress diagnostics flag, and restore
/// the spell checking language options.
///
class ParserStateRAII {
private :
Parser * P ;
Preprocessor & PP ;
bool ResetIncrementalProcessing ;
bool OldSuppressAllDiagnostics ;
bool OldSpellChecking ;
2012-11-16 00:19:21 +04:00
DestroyTemplateIdAnnotationsRAIIObj CleanupTemplateIds ;
2012-09-05 13:37:39 +04:00
public :
2012-11-20 17:17:55 +04:00
ParserStateRAII ( Parser & p )
2013-08-03 09:48:28 +04:00
: P ( & p ) , PP ( p . getPreprocessor ( ) ) ,
2013-02-19 13:25:04 +04:00
ResetIncrementalProcessing ( p . getPreprocessor ( )
. isIncrementalProcessingEnabled ( ) ) ,
OldSuppressAllDiagnostics ( p . getPreprocessor ( ) . getDiagnostics ( )
. getSuppressAllDiagnostics ( ) ) ,
OldSpellChecking ( p . getPreprocessor ( ) . getLangOpts ( ) . SpellChecking ) ,
CleanupTemplateIds ( p )
{
}
2012-09-05 13:37:39 +04:00
~ ParserStateRAII ( )
{
//
// Advance the parser to the end of the file, and pop the include stack.
//
// Note: Consuming the EOF token will pop the include stack.
//
2013-08-03 09:48:28 +04:00
P - > SkipUntil ( tok : : eof , /*StopAtSemi*/ false , /*DontConsume*/ false ,
2012-09-18 15:45:00 +04:00
/*StopAtCodeCompletion*/ false ) ;
2012-10-12 20:09:04 +04:00
PP . enableIncrementalProcessing ( ResetIncrementalProcessing ) ;
2012-10-14 15:44:16 +04:00
P - > getActions ( ) . getDiagnostics ( ) . Reset ( ) ;
2012-09-05 13:37:39 +04:00
PP . getDiagnostics ( ) . setSuppressAllDiagnostics ( OldSuppressAllDiagnostics ) ;
const_cast < LangOptions & > ( PP . getLangOpts ( ) ) . SpellChecking =
OldSpellChecking ;
}
} ;
2012-11-26 17:45:32 +04:00
// pin *tor here so that we can have clang::Parser defined and be able to call
// the dtor on the OwningPtr
2013-08-03 09:48:28 +04:00
LookupHelper : : LookupHelper ( clang : : Parser * P , Interpreter * interp )
2013-04-03 20:25:08 +04:00
: m_Parser ( P ) , m_Interpreter ( interp ) { }
2012-11-26 17:45:32 +04:00
LookupHelper : : ~ LookupHelper ( ) { }
2012-10-12 19:27:02 +04:00
2012-09-05 13:37:39 +04:00
QualType LookupHelper : : findType ( llvm : : StringRef typeName ) const {
//
// Our return value.
//
QualType TheQT ;
2013-08-15 17:33:14 +04:00
// Could trigger deserialization of decls.
Interpreter : : PushTransactionRAII RAII ( m_Interpreter ) ;
2012-09-05 13:37:39 +04:00
// Use P for shortness
Parser & P = * m_Parser ;
2012-11-20 17:17:55 +04:00
ParserStateRAII ResetParserState ( P ) ;
2012-10-12 19:27:02 +04:00
prepareForParsing ( typeName , llvm : : StringRef ( " lookup.type.by.name.file " ) ) ;
2012-09-05 13:37:39 +04:00
//
// Try parsing the type name.
//
2012-09-18 15:45:00 +04:00
TypeResult Res ( P . ParseTypeName ( ) ) ;
2012-09-05 13:37:39 +04:00
if ( Res . isUsable ( ) ) {
// Accept it only if the whole name was parsed.
2012-09-18 15:45:00 +04:00
if ( P . NextToken ( ) . getKind ( ) = = clang : : tok : : eof ) {
2012-09-05 13:37:39 +04:00
TypeSourceInfo * TSI = 0 ;
TheQT = clang : : Sema : : GetTypeFromParser ( Res . get ( ) , & TSI ) ;
}
}
return TheQT ;
}
const Decl * LookupHelper : : findScope ( llvm : : StringRef className ,
2012-12-09 05:51:25 +04:00
const Type * * resultType /* = 0 */ ,
bool instantiateTemplate /*=true*/ ) const {
2012-09-05 13:37:39 +04:00
//
// Some utilities.
//
// Use P for shortness
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
Preprocessor & PP = P . getPreprocessor ( ) ;
ASTContext & Context = S . getASTContext ( ) ;
2013-04-08 14:16:01 +04:00
2013-08-03 09:48:28 +04:00
// The user wants to see the template instantiation, existing or not.
// Here we might not have an active transaction to handle
// the caused instantiation decl.
2013-04-08 14:16:01 +04:00
Interpreter : : PushTransactionRAII pushedT ( m_Interpreter ) ;
2012-11-20 17:17:55 +04:00
ParserStateRAII ResetParserState ( P ) ;
2013-08-03 09:48:28 +04:00
prepareForParsing ( className . str ( ) + " :: " ,
2012-10-12 20:09:04 +04:00
llvm : : StringRef ( " lookup.class.by.name.file " ) ) ;
2012-09-05 13:37:39 +04:00
//
2012-10-12 20:09:04 +04:00
// Our return values.
2012-09-05 13:37:39 +04:00
//
2012-10-12 20:09:04 +04:00
const Type * TheType = 0 ;
const Type * * setResultType = & TheType ;
if ( resultType )
setResultType = resultType ;
* setResultType = 0 ;
const Decl * TheDecl = 0 ;
2012-09-05 13:37:39 +04:00
//
// Prevent failing on an assert in TryAnnotateCXXScopeToken.
//
2013-08-03 09:48:28 +04:00
if ( ! P . getCurToken ( ) . is ( clang : : tok : : identifier )
& & ! P . getCurToken ( ) . is ( clang : : tok : : coloncolon )
& & ! ( P . getCurToken ( ) . is ( clang : : tok : : annot_template_id )
& & P . NextToken ( ) . is ( clang : : tok : : coloncolon ) )
2012-12-01 11:22:56 +04:00
& & ! P . getCurToken ( ) . is ( clang : : tok : : kw_decltype ) ) {
2012-09-05 13:37:39 +04:00
// error path
return TheDecl ;
}
//
// Try parsing the name as a nested-name-specifier.
//
2012-09-18 15:45:00 +04:00
if ( P . TryAnnotateCXXScopeToken ( false ) ) {
2012-09-05 13:37:39 +04:00
// error path
return TheDecl ;
}
if ( P . getCurToken ( ) . getKind ( ) = = tok : : annot_cxxscope ) {
CXXScopeSpec SS ;
S . RestoreNestedNameSpecifierAnnotation ( P . getCurToken ( ) . getAnnotationValue ( ) ,
P . getCurToken ( ) . getAnnotationRange ( ) ,
SS ) ;
if ( SS . isValid ( ) ) {
NestedNameSpecifier * NNS = SS . getScopeRep ( ) ;
NestedNameSpecifier : : SpecifierKind Kind = NNS - > getKind ( ) ;
// Only accept the parse if we consumed all of the name.
2012-09-18 15:45:00 +04:00
if ( P . NextToken ( ) . getKind ( ) = = clang : : tok : : eof ) {
2012-09-05 13:37:39 +04:00
//
// Be careful, not all nested name specifiers refer to classes
// and namespaces, and those are the only things we want.
//
switch ( Kind ) {
case NestedNameSpecifier : : Identifier : {
// Dependent type.
// We do not accept these.
}
break ;
case NestedNameSpecifier : : Namespace : {
// Namespace.
NamespaceDecl * NSD = NNS - > getAsNamespace ( ) ;
NSD = NSD - > getCanonicalDecl ( ) ;
TheDecl = NSD ;
}
break ;
case NestedNameSpecifier : : NamespaceAlias : {
// Namespace alias.
// Note: In the future, should we return the alias instead?
NamespaceAliasDecl * NSAD = NNS - > getAsNamespaceAlias ( ) ;
NamespaceDecl * NSD = NSAD - > getNamespace ( ) ;
NSD = NSD - > getCanonicalDecl ( ) ;
TheDecl = NSD ;
}
break ;
case NestedNameSpecifier : : TypeSpec :
// Type name.
2012-09-28 10:48:09 +04:00
// Intentional fall-though
2012-09-05 13:37:39 +04:00
case NestedNameSpecifier : : TypeSpecWithTemplate : {
// Type name qualified with "template".
// Note: Do we need to check for a dependent type here?
NestedNameSpecifier * prefix = NNS - > getPrefix ( ) ;
if ( prefix ) {
2013-08-03 09:48:28 +04:00
QualType temp
2012-10-14 15:44:16 +04:00
= Context . getElaboratedType ( ETK_None , prefix ,
QualType ( NNS - > getAsType ( ) , 0 ) ) ;
2012-09-05 13:37:39 +04:00
* setResultType = temp . getTypePtr ( ) ;
} else {
* setResultType = NNS - > getAsType ( ) ;
}
const TagType * TagTy = ( * setResultType ) - > getAs < TagType > ( ) ;
if ( TagTy ) {
// It is a class, struct, or union.
TagDecl * TD = TagTy - > getDecl ( ) ;
if ( TD ) {
2013-04-06 20:43:35 +04:00
TheDecl = TD - > getDefinition ( ) ;
if ( ! TheDecl & & instantiateTemplate ) {
2013-04-06 20:44:22 +04:00
2012-12-09 05:51:25 +04:00
// Make sure it is not just forward declared, and
// instantiate any templates.
if ( ! S . RequireCompleteDeclContext ( SS , TD ) ) {
// Success, type is complete, instantiations have
// been done.
2013-04-06 20:43:35 +04:00
TheDecl = TD - > getDefinition ( ) ;
2012-09-05 13:37:39 +04:00
}
}
}
}
}
break ;
case clang : : NestedNameSpecifier : : Global : {
// Name was just "::" and nothing more.
TheDecl = Context . getTranslationUnitDecl ( ) ;
}
break ;
}
return TheDecl ;
}
}
}
2012-10-26 17:32:41 +04:00
//
// Cleanup after failed parse as a nested-name-specifier.
//
P . SkipUntil ( clang : : tok : : eof , /*StopAtSemi*/ false , /*DontConsume*/ false ,
/*StopAtCodeCompletion*/ false ) ;
S . getDiagnostics ( ) . Reset ( ) ;
//
// Setup to reparse as a type.
//
2013-02-19 13:25:04 +04:00
llvm : : MemoryBuffer * SB =
2013-02-19 13:28:40 +04:00
llvm : : MemoryBuffer : : getMemBufferCopy ( className . str ( ) + " \n " ,
2013-02-19 13:25:04 +04:00
" lookup.type.file " ) ;
clang : : FileID FID = S . getSourceManager ( ) . createFileIDForMemBuffer ( SB ) ;
PP . EnterSourceFile ( FID , 0 , clang : : SourceLocation ( ) ) ;
PP . Lex ( const_cast < clang : : Token & > ( P . getCurToken ( ) ) ) ;
2012-09-05 13:37:39 +04:00
//
// Now try to parse the name as a type.
//
2012-09-18 15:45:00 +04:00
if ( P . TryAnnotateTypeOrScopeToken ( false , false ) ) {
2012-09-05 13:37:39 +04:00
// error path
return TheDecl ;
}
if ( P . getCurToken ( ) . getKind ( ) = = tok : : annot_typename ) {
2012-09-18 15:45:00 +04:00
ParsedType T = P . getTypeAnnotation ( const_cast < Token & > ( P . getCurToken ( ) ) ) ;
2012-09-05 13:37:39 +04:00
// Only accept the parse if we consumed all of the name.
2013-02-19 13:30:00 +04:00
if ( P . NextToken ( ) . getKind ( ) = = clang : : tok : : eof )
if ( ! T . get ( ) . isNull ( ) ) {
TypeSourceInfo * TSI = 0 ;
clang : : QualType QT = clang : : Sema : : GetTypeFromParser ( T , & TSI ) ;
if ( const TagType * TT = QT - > getAs < TagType > ( ) ) {
TheDecl = TT - > getDecl ( ) - > getDefinition ( ) ;
* setResultType = QT . getTypePtr ( ) ;
}
2012-09-05 13:37:39 +04:00
}
}
return TheDecl ;
}
2012-12-01 11:22:56 +04:00
const ClassTemplateDecl * LookupHelper : : findClassTemplate ( llvm : : StringRef Name ) const {
//
// Find a class template decl given its name.
//
// Humm ... this seems to do the trick ... or does it? or is there a better way?
// Use P for shortness
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
ASTContext & Context = S . getASTContext ( ) ;
ParserStateRAII ResetParserState ( P ) ;
2013-08-03 09:48:28 +04:00
prepareForParsing ( Name . str ( ) ,
2012-12-01 11:22:56 +04:00
llvm : : StringRef ( " lookup.class.by.name.file " ) ) ;
//
// Prevent failing on an assert in TryAnnotateCXXScopeToken.
//
2013-08-03 09:48:28 +04:00
if ( ! P . getCurToken ( ) . is ( clang : : tok : : identifier )
& & ! P . getCurToken ( ) . is ( clang : : tok : : coloncolon )
& & ! ( P . getCurToken ( ) . is ( clang : : tok : : annot_template_id )
& & P . NextToken ( ) . is ( clang : : tok : : coloncolon ) )
2012-12-01 11:22:56 +04:00
& & ! P . getCurToken ( ) . is ( clang : : tok : : kw_decltype ) ) {
// error path
return 0 ;
}
//
// Now try to parse the name as a type.
//
if ( P . TryAnnotateTypeOrScopeToken ( false , false ) ) {
// error path
return 0 ;
}
DeclContext * where = 0 ;
if ( P . getCurToken ( ) . getKind ( ) = = tok : : annot_cxxscope ) {
CXXScopeSpec SS ;
S . RestoreNestedNameSpecifierAnnotation ( P . getCurToken ( ) . getAnnotationValue ( ) ,
P . getCurToken ( ) . getAnnotationRange ( ) ,
SS ) ;
if ( SS . isValid ( ) ) {
P . ConsumeToken ( ) ;
if ( ! P . getCurToken ( ) . is ( clang : : tok : : identifier ) ) {
return 0 ;
}
NestedNameSpecifier * nested = SS . getScopeRep ( ) ;
if ( ! nested ) return 0 ;
switch ( nested - > getKind ( ) ) {
case NestedNameSpecifier : : Global :
where = Context . getTranslationUnitDecl ( ) ;
break ;
case NestedNameSpecifier : : Namespace :
where = nested - > getAsNamespace ( ) ;
break ;
case NestedNameSpecifier : : NamespaceAlias :
case NestedNameSpecifier : : Identifier :
return 0 ;
case NestedNameSpecifier : : TypeSpec :
2013-08-03 09:48:28 +04:00
case NestedNameSpecifier : : TypeSpecWithTemplate :
2012-12-01 11:22:56 +04:00
{
const Type * ntype = nested - > getAsType ( ) ;
where = ntype - > getAsCXXRecordDecl ( ) ;
if ( ! where ) return 0 ;
break ;
}
} ;
}
} else if ( P . getCurToken ( ) . is ( clang : : tok : : identifier ) ) {
// We have a single indentifier, let's look for it in the
// the global scope.
where = Context . getTranslationUnitDecl ( ) ;
}
if ( where ) {
// Great we now have a scope and something to search for,let's go ahead.
2013-08-03 09:48:28 +04:00
DeclContext : : lookup_result R
2013-04-24 20:28:08 +04:00
= where - > lookup ( P . getCurToken ( ) . getIdentifierInfo ( ) ) ;
for ( DeclContext : : lookup_iterator I = R . begin ( ) , E = R . end ( ) ;
I ! = E ; + + I ) {
ClassTemplateDecl * theDecl = dyn_cast < ClassTemplateDecl > ( * I ) ;
2012-12-01 11:22:56 +04:00
if ( theDecl )
return theDecl ;
}
}
return 0 ;
}
2013-08-03 09:48:28 +04:00
static
DeclContext * getContextAndSpec ( CXXScopeSpec & SS ,
const Decl * scopeDecl ,
ASTContext & Context , Sema & S ) {
2012-09-05 13:37:39 +04:00
//
2013-08-03 09:48:28 +04:00
// Convert the passed decl into a nested name specifier,
// a scope spec, and a decl context.
2012-09-05 13:37:39 +04:00
//
NestedNameSpecifier * classNNS = 0 ;
if ( const NamespaceDecl * NSD = dyn_cast < NamespaceDecl > ( scopeDecl ) ) {
classNNS = NestedNameSpecifier : : Create ( Context , 0 ,
const_cast < NamespaceDecl * > ( NSD ) ) ;
}
else if ( const RecordDecl * RD = dyn_cast < RecordDecl > ( scopeDecl ) ) {
const Type * T = Context . getRecordType ( RD ) . getTypePtr ( ) ;
classNNS = NestedNameSpecifier : : Create ( Context , 0 , false , T ) ;
}
else if ( llvm : : isa < TranslationUnitDecl > ( scopeDecl ) ) {
classNNS = NestedNameSpecifier : : GlobalSpecifier ( Context ) ;
}
else {
// Not a namespace or class, we cannot use it.
return 0 ;
}
DeclContext * foundDC = dyn_cast < DeclContext > ( const_cast < Decl * > ( scopeDecl ) ) ;
2013-08-03 09:48:28 +04:00
//
// Some validity checks on the passed decl.
//
if ( foundDC - > isDependentContext ( ) ) {
// Passed decl is a template, we cannot use it.
return 0 ;
}
SS . MakeTrivial ( Context , classNNS , SourceRange ( ) ) ;
if ( S . RequireCompleteDeclContext ( SS , foundDC ) ) {
// Forward decl or instantiation failure, we cannot use it.
return 0 ;
}
return foundDC ;
}
static
const FunctionDecl * overloadFunctionSelector ( DeclContext * foundDC ,
const llvm : : SmallVector < Expr * , 4 > & GivenArgs ,
LookupResult & Result ,
DeclarationNameInfo & FuncNameInfo ,
const TemplateArgumentListInfo * FuncTemplateArgs ,
ASTContext & Context , Parser & P , Sema & S ) {
//
// Our return value.
//
FunctionDecl * TheDecl = 0 ;
2012-09-05 13:37:39 +04:00
//
2012-10-11 00:14:23 +04:00
// If we are looking up a member function, construct
// the implicit object argument.
//
// Note: For now this is always a non-CV qualified lvalue.
//
QualType ClassType ;
Expr * ObjExpr = 0 ;
Expr : : Classification ObjExprClassification ;
if ( CXXRecordDecl * CRD = dyn_cast < CXXRecordDecl > ( foundDC ) ) {
ClassType = Context . getTypeDeclType ( CRD ) . getCanonicalType ( ) ;
2013-08-03 09:48:28 +04:00
OpaqueValueExpr ObjExpr ( SourceLocation ( ) ,
ClassType , VK_LValue ) ;
ObjExprClassification = ObjExpr . Classify ( Context ) ;
}
//
// Construct the overload candidate set.
//
OverloadCandidateSet Candidates ( FuncNameInfo . getLoc ( ) ) ;
for ( LookupResult : : iterator I = Result . begin ( ) , E = Result . end ( ) ;
I ! = E ; + + I ) {
NamedDecl * ND = * I ;
if ( FunctionDecl * FD = dyn_cast < FunctionDecl > ( ND ) ) {
if ( isa < CXXMethodDecl > ( FD ) & &
! cast < CXXMethodDecl > ( FD ) - > isStatic ( ) & &
! isa < CXXConstructorDecl > ( FD ) ) {
// Class method, not static, not a constructor, so has
// an implicit object argument.
CXXMethodDecl * MD = cast < CXXMethodDecl > ( FD ) ;
if ( FuncTemplateArgs & & ( FuncTemplateArgs - > size ( ) ! = 0 ) ) {
// Explicit template args were given, cannot use a plain func.
continue ;
}
S . AddMethodCandidate ( MD , I . getPair ( ) , MD - > getParent ( ) ,
/*ObjectType=*/ ClassType ,
/*ObjectClassification=*/ ObjExprClassification ,
llvm : : makeArrayRef < Expr * > ( GivenArgs . data ( ) , GivenArgs . size ( ) ) ,
Candidates ) ;
}
else {
const FunctionProtoType * Proto = dyn_cast < FunctionProtoType > (
FD - > getType ( ) - > getAs < clang : : FunctionType > ( ) ) ;
if ( ! Proto ) {
// Function has no prototype, cannot do overloading.
continue ;
}
if ( FuncTemplateArgs & & ( FuncTemplateArgs - > size ( ) ! = 0 ) ) {
// Explicit template args were given, cannot use a plain func.
continue ;
}
S . AddOverloadCandidate ( FD , I . getPair ( ) ,
llvm : : makeArrayRef < Expr * > ( GivenArgs . data ( ) , GivenArgs . size ( ) ) ,
Candidates ) ;
}
}
else if ( FunctionTemplateDecl * FTD =
dyn_cast < FunctionTemplateDecl > ( ND ) ) {
if ( isa < CXXMethodDecl > ( FTD - > getTemplatedDecl ( ) ) & &
! cast < CXXMethodDecl > ( FTD - > getTemplatedDecl ( ) ) - > isStatic ( ) & &
! isa < CXXConstructorDecl > ( FTD - > getTemplatedDecl ( ) ) ) {
// Class method template, not static, not a constructor, so has
// an implicit object argument.
S . AddMethodTemplateCandidate ( FTD , I . getPair ( ) ,
cast < CXXRecordDecl > ( FTD - > getDeclContext ( ) ) ,
const_cast < TemplateArgumentListInfo * > ( FuncTemplateArgs ) ,
/*ObjectType=*/ ClassType ,
/*ObjectClassification=*/ ObjExprClassification ,
llvm : : makeArrayRef < Expr * > ( GivenArgs . data ( ) , GivenArgs . size ( ) ) ,
Candidates ) ;
}
else {
S . AddTemplateOverloadCandidate ( FTD , I . getPair ( ) ,
const_cast < TemplateArgumentListInfo * > ( FuncTemplateArgs ) ,
llvm : : makeArrayRef < Expr * > ( GivenArgs . data ( ) , GivenArgs . size ( ) ) ,
Candidates , /*SuppressUserConversions=*/ false ) ;
}
}
else {
// Is there any other cases?
}
}
//
// Find the best viable function from the set.
//
{
OverloadCandidateSet : : iterator Best ;
OverloadingResult OR = Candidates . BestViableFunction ( S ,
Result . getNameLoc ( ) ,
Best ) ;
if ( OR = = OR_Success ) {
TheDecl = Best - > Function ;
// We prefer to get the canonical decl for consistency and ease
// of comparison.
TheDecl = TheDecl - > getCanonicalDecl ( ) ;
}
}
return TheDecl ;
}
template < typename T >
T findFunction ( DeclContext * foundDC , CXXScopeSpec & SS ,
llvm : : StringRef funcName ,
const llvm : : SmallVector < Expr * , 4 > & GivenArgs ,
ASTContext & Context , Parser & P , Sema & S ,
T ( * functionSelector ) ( DeclContext * foundDC ,
const llvm : : SmallVector < Expr * , 4 > & GivenArgs ,
LookupResult & Result ,
DeclarationNameInfo & FuncNameInfo ,
const TemplateArgumentListInfo * FuncTemplateArgs ,
ASTContext & Context , Parser & P , Sema & S )
) {
// Given the correctly types arguments, etc. find the function itself.
//
// Some utilities.
//
Preprocessor & PP = S . getPreprocessor ( ) ;
//
// Our return value.
//
FunctionDecl * TheDecl = 0 ;
//
// Setup to reparse as a type.
//
//
// Create a fake file to parse the function name.
//
{
llvm : : MemoryBuffer * SB
= llvm : : MemoryBuffer : : getMemBufferCopy ( funcName . str ( )
+ " \n " , " lookup.funcname.file " ) ;
clang : : FileID FID = S . getSourceManager ( ) . createFileIDForMemBuffer ( SB ) ;
PP . EnterSourceFile ( FID , /*DirLookup=*/ 0 , clang : : SourceLocation ( ) ) ;
PP . Lex ( const_cast < clang : : Token & > ( P . getCurToken ( ) ) ) ;
2012-10-11 00:14:23 +04:00
}
2013-08-03 09:48:28 +04:00
//
// Make the class we are looking up the function
// in the current scope to please the constructor
// name lookup. We do not need to do this otherwise,
// and may be able to remove it in the future if
// the way constructors are looked up changes.
//
void * OldEntity = P . getCurScope ( ) - > getEntity ( ) ;
DeclContext * TUCtx = Context . getTranslationUnitDecl ( ) ;
P . getCurScope ( ) - > setEntity ( TUCtx ) ;
P . EnterScope ( Scope : : DeclScope ) ;
P . getCurScope ( ) - > setEntity ( foundDC ) ;
P . EnterScope ( Scope : : DeclScope ) ;
Sema : : ContextRAII SemaContext ( S , foundDC ) ;
S . EnterDeclaratorContext ( P . getCurScope ( ) , foundDC ) ;
//
// Parse the function name.
//
SourceLocation TemplateKWLoc ;
UnqualifiedId FuncId ;
if ( P . ParseUnqualifiedId ( SS , /*EnteringContext*/ false ,
/*AllowDestructorName*/ true ,
/*AllowConstructorName*/ true ,
ParsedType ( ) , TemplateKWLoc ,
FuncId ) ) {
// Failed parse, cleanup.
// Destroy the scope we created first, and
// restore the original.
S . ExitDeclaratorContext ( P . getCurScope ( ) ) ;
P . ExitScope ( ) ;
P . ExitScope ( ) ;
P . getCurScope ( ) - > setEntity ( OldEntity ) ;
// Then exit.
return TheDecl ;
}
//
// Get any template args in the function name.
//
TemplateArgumentListInfo FuncTemplateArgsBuffer ;
DeclarationNameInfo FuncNameInfo ;
const TemplateArgumentListInfo * FuncTemplateArgs ;
S . DecomposeUnqualifiedId ( FuncId , FuncTemplateArgsBuffer , FuncNameInfo ,
FuncTemplateArgs ) ;
//
// Lookup the function name in the given class now.
//
DeclarationName FuncName = FuncNameInfo . getName ( ) ;
SourceLocation FuncNameLoc = FuncNameInfo . getLoc ( ) ;
LookupResult Result ( S , FuncName , FuncNameLoc , Sema : : LookupMemberName ,
Sema : : NotForRedeclaration ) ;
Interpreter : : PushTransactionRAII pushedT ( m_Interpreter ) ;
if ( ! S . LookupQualifiedName ( Result , foundDC ) ) {
// Lookup failed.
// Destroy the scope we created first, and
// restore the original.
S . ExitDeclaratorContext ( P . getCurScope ( ) ) ;
P . ExitScope ( ) ;
P . ExitScope ( ) ;
P . getCurScope ( ) - > setEntity ( OldEntity ) ;
// Then cleanup and exit.
return TheDecl ;
}
//
// Destroy the scope we created, and restore the original.
//
S . ExitDeclaratorContext ( P . getCurScope ( ) ) ;
P . ExitScope ( ) ;
P . ExitScope ( ) ;
P . getCurScope ( ) - > setEntity ( OldEntity ) ;
//
// Check for lookup failure.
//
if ( Result . getResultKind ( ) ! = LookupResult : : Found & &
Result . getResultKind ( ) ! = LookupResult : : FoundOverloaded ) {
// Lookup failed.
return TheDecl ;
}
return functionSelector ( foundDC , GivenArgs ,
Result ,
FuncNameInfo ,
FuncTemplateArgs ,
Context , P , S ) ;
}
static
bool findFunctionParseProto ( llvm : : SmallVector < Expr * , 4 > & GivenArgs ,
ASTContext & Context , Parser & P , Sema & S ) {
2012-10-11 00:14:23 +04:00
//
2012-09-05 13:37:39 +04:00
// Parse the prototype now.
//
2013-08-03 09:48:28 +04:00
2012-09-05 13:37:39 +04:00
llvm : : SmallVector < QualType , 4 > GivenArgTypes ;
2013-08-03 09:48:28 +04:00
2012-09-05 13:37:39 +04:00
while ( P . getCurToken ( ) . isNot ( tok : : eof ) ) {
2012-09-18 15:45:00 +04:00
TypeResult Res ( P . ParseTypeName ( ) ) ;
2012-09-05 13:37:39 +04:00
if ( ! Res . isUsable ( ) ) {
// Bad parse, done.
2013-08-03 09:48:28 +04:00
return false ;
2012-09-05 13:37:39 +04:00
}
TypeSourceInfo * TSI = 0 ;
2012-12-01 02:42:53 +04:00
clang : : QualType QT = clang : : Sema : : GetTypeFromParser ( Res . get ( ) , & TSI ) ;
2012-09-05 13:37:39 +04:00
QT = QT . getCanonicalType ( ) ;
GivenArgTypes . push_back ( QT ) ;
{
2012-10-11 02:55:40 +04:00
ExprValueKind VK = VK_RValue ;
if ( QT - > getAs < LValueReferenceType > ( ) ) {
VK = VK_LValue ;
}
2012-09-05 13:37:39 +04:00
clang : : QualType NonRefQT ( QT . getNonReferenceType ( ) ) ;
2013-06-21 12:38:40 +04:00
Expr * val
= new ( Context ) OpaqueValueExpr ( TSI - > getTypeLoc ( ) . getLocStart ( ) ,
NonRefQT , VK ) ;
2012-09-05 13:37:39 +04:00
GivenArgs . push_back ( val ) ;
}
// Type names should be comma separated.
2013-03-25 20:17:01 +04:00
// FIXME: Here if we have type followed by name won't work. Eg int f, ...
2012-09-05 13:37:39 +04:00
if ( ! P . getCurToken ( ) . is ( clang : : tok : : comma ) ) {
break ;
}
// Eat the comma.
2012-09-18 15:45:00 +04:00
P . ConsumeToken ( ) ;
2012-09-05 13:37:39 +04:00
}
if ( P . getCurToken ( ) . isNot ( tok : : eof ) ) {
// We did not consume all of the prototype, bad parse.
2013-08-03 09:48:28 +04:00
return false ;
2012-09-05 13:37:39 +04:00
}
//
2012-10-26 17:32:41 +04:00
// Cleanup after prototype parse.
//
2013-08-03 09:48:28 +04:00
P . SkipUntil ( clang : : tok : : eof , /*StopAtSemi*/ false , /*DontConsume*/ false ,
2012-10-26 17:32:41 +04:00
/*StopAtCodeCompletion*/ false ) ;
S . getDiagnostics ( ) . Reset ( ) ;
2013-08-03 09:48:28 +04:00
return true ;
}
const FunctionDecl * LookupHelper : : findFunctionProto ( const Decl * scopeDecl ,
llvm : : StringRef funcName ,
llvm : : StringRef funcProto ) const {
assert ( scopeDecl & & " Decl cannot be null " ) ;
2012-10-26 17:32:41 +04:00
//
2013-08-03 09:48:28 +04:00
// Some utilities.
2012-10-26 17:32:41 +04:00
//
2013-08-03 09:48:28 +04:00
// Use P for shortness
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
ASTContext & Context = S . getASTContext ( ) ;
2012-10-26 17:32:41 +04:00
//
2013-08-03 09:48:28 +04:00
// Convert the passed decl into a nested name specifier,
// a scope spec, and a decl context.
2012-09-05 13:37:39 +04:00
//
2013-08-03 09:48:28 +04:00
// Do this 'early' to save on the expansive parser setup,
// in case of failure.
//
CXXScopeSpec SS ;
DeclContext * foundDC = getContextAndSpec ( SS , scopeDecl , Context , S ) ;
if ( ! foundDC ) return 0 ;
//
// Parse the prototype now.
//
ParserStateRAII ResetParserState ( P ) ;
prepareForParsing ( funcProto , llvm : : StringRef ( " func.prototype.file " ) ) ;
llvm : : SmallVector < Expr * , 4 > GivenArgs ;
if ( ! findFunctionParseProto ( GivenArgs , Context , P , S ) ) {
return 0 ;
2012-09-05 13:37:39 +04:00
}
2013-08-03 09:48:28 +04:00
return findFunction ( foundDC , SS ,
funcName , GivenArgs ,
Context , P , S ,
overloadFunctionSelector ) ;
}
static
bool findFunctionParseArgs ( llvm : : SmallVector < Expr * , 4 > & GivenArgs ,
ASTContext & Context , Parser & P , Sema & S ) {
//
// Parse the arguments now.
//
llvm : : SmallVector < QualType , 4 > GivenArgTypes ;
PrintingPolicy Policy ( Context . getPrintingPolicy ( ) ) ;
Policy . SuppressTagKeyword = true ;
Policy . SuppressUnwrittenScope = true ;
Policy . SuppressInitializers = true ;
Policy . AnonymousTagLocations = false ;
std : : string proto ;
2012-09-05 13:37:39 +04:00
{
2013-08-03 09:48:28 +04:00
bool first_time = true ;
while ( P . getCurToken ( ) . isNot ( tok : : eof ) ) {
ExprResult Res = P . ParseAssignmentExpression ( ) ;
if ( Res . isUsable ( ) ) {
Expr * expr = Res . release ( ) ;
GivenArgs . push_back ( expr ) ;
QualType QT = expr - > getType ( ) . getCanonicalType ( ) ;
QualType NonRefQT ( QT . getNonReferenceType ( ) ) ;
GivenArgTypes . push_back ( NonRefQT ) ;
if ( first_time ) {
first_time = false ;
2012-09-05 13:37:39 +04:00
}
2013-08-03 09:48:28 +04:00
else {
proto + = ' , ' ;
2012-10-11 00:14:23 +04:00
}
2013-08-03 09:48:28 +04:00
std : : string empty ;
llvm : : raw_string_ostream tmp ( empty ) ;
expr - > printPretty ( tmp , /*PrinterHelper=*/ 0 , Policy ,
/*Indentation=*/ 0 ) ;
proto + = tmp . str ( ) ;
2012-10-11 00:14:23 +04:00
}
2013-08-03 09:48:28 +04:00
if ( ! P . getCurToken ( ) . is ( tok : : comma ) ) {
break ;
2012-09-05 13:37:39 +04:00
}
2013-08-03 09:48:28 +04:00
P . ConsumeToken ( ) ;
2012-09-05 13:37:39 +04:00
}
}
2013-08-03 09:48:28 +04:00
// For backward compatibility with CINT accept (for now?) a trailing close
// parenthesis.
if ( P . getCurToken ( ) . isNot ( tok : : eof ) & & P . getCurToken ( ) . isNot ( tok : : r_paren ) ) {
// We did not consume all of the arg list, bad parse.
return false ;
}
//
// Cleanup after the arg list parse.
//
P . SkipUntil ( clang : : tok : : eof , /*StopAtSemi*/ false , /*DontConsume*/ false ,
/*StopAtCodeCompletion*/ false ) ;
S . getDiagnostics ( ) . Reset ( ) ;
return true ;
2012-09-05 13:37:39 +04:00
}
const FunctionDecl * LookupHelper : : findFunctionArgs ( const Decl * scopeDecl ,
llvm : : StringRef funcName ,
llvm : : StringRef funcArgs ) const {
2013-08-03 09:48:28 +04:00
assert ( scopeDecl & & " Decl cannot be null " ) ;
2012-09-05 13:37:39 +04:00
//
// Some utilities.
//
// Use P for shortness
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
ASTContext & Context = S . getASTContext ( ) ;
2012-10-12 20:09:04 +04:00
2012-09-05 13:37:39 +04:00
//
// Convert the passed decl into a nested name specifier,
// a scope spec, and a decl context.
//
2013-08-03 09:48:28 +04:00
// Do this 'early' to save on the expansive parser setup,
// in case of failure.
2012-09-05 13:37:39 +04:00
//
2013-08-03 09:48:28 +04:00
CXXScopeSpec SS ;
DeclContext * foundDC = getContextAndSpec ( SS , scopeDecl , Context , S ) ;
if ( ! foundDC ) return 0 ;
2012-10-12 20:09:04 +04:00
2012-09-05 13:37:39 +04:00
//
// Parse the arguments now.
//
2013-08-03 09:48:28 +04:00
ParserStateRAII ResetParserState ( P ) ;
prepareForParsing ( funcArgs , llvm : : StringRef ( " func.args.file " ) ) ;
llvm : : SmallVector < Expr * , 4 > GivenArgs ;
if ( ! findFunctionParseArgs ( GivenArgs , Context , P , S ) ) {
return 0 ;
2012-09-05 13:37:39 +04:00
}
2013-08-03 09:48:28 +04:00
return findFunction ( foundDC , SS ,
funcName , GivenArgs ,
Context , P , S , overloadFunctionSelector ) ;
2012-09-05 13:37:39 +04:00
}
void LookupHelper : : findArgList ( llvm : : StringRef argList ,
llvm : : SmallVector < Expr * , 4 > & argExprs ) const {
//
// Some utilities.
//
// Use P for shortness
Parser & P = * m_Parser ;
2012-11-20 17:17:55 +04:00
ParserStateRAII ResetParserState ( P ) ;
2012-10-12 20:09:04 +04:00
prepareForParsing ( argList , llvm : : StringRef ( " arg.list.file " ) ) ;
2012-10-14 15:44:16 +04:00
//
2012-09-05 13:37:39 +04:00
// Parse the arguments now.
//
{
bool hasUnusableResult = false ;
while ( P . getCurToken ( ) . isNot ( tok : : eof ) ) {
2012-09-18 15:45:00 +04:00
ExprResult Res = P . ParseAssignmentExpression ( ) ;
2012-09-05 13:37:39 +04:00
if ( Res . isUsable ( ) ) {
argExprs . push_back ( Res . release ( ) ) ;
}
else {
hasUnusableResult = true ;
break ;
}
if ( ! P . getCurToken ( ) . is ( tok : : comma ) ) {
break ;
}
2012-09-18 15:45:00 +04:00
P . ConsumeToken ( ) ;
2012-09-05 13:37:39 +04:00
}
if ( hasUnusableResult )
// if one of the arguments is not usable return empty.
argExprs . clear ( ) ;
}
}
2013-08-03 09:48:28 +04:00
void LookupHelper : : prepareForParsing ( llvm : : StringRef code ,
2012-10-12 19:27:02 +04:00
llvm : : StringRef bufferName ) const {
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
Preprocessor & PP = P . getPreprocessor ( ) ;
//
// Tell the diagnostic engine to ignore all diagnostics.
//
PP . getDiagnostics ( ) . setSuppressAllDiagnostics ( true ) ;
//
// Tell the parser to not attempt spelling correction.
//
const_cast < LangOptions & > ( PP . getLangOpts ( ) ) . SpellChecking = 0 ;
//
// Create a fake file to parse the type name.
//
2013-08-03 09:48:28 +04:00
llvm : : MemoryBuffer * SB
2012-10-12 19:27:02 +04:00
= llvm : : MemoryBuffer : : getMemBufferCopy ( code . str ( ) + " \n " ,
bufferName . str ( ) ) ;
FileID FID = S . getSourceManager ( ) . createFileIDForMemBuffer ( SB ) ;
//
// Turn on ignoring of the main file eof token.
//
// Note: We need this because token readahead in the following
// routine calls ends up parsing it multiple times.
//
if ( ! PP . isIncrementalProcessingEnabled ( ) ) {
PP . enableIncrementalProcessing ( ) ;
}
//
// Switch to the new file the way #include does.
//
// Note: To switch back to the main file we must consume an eof token.
//
PP . EnterSourceFile ( FID , /*DirLookup=*/ 0 , SourceLocation ( ) ) ;
PP . Lex ( const_cast < Token & > ( P . getCurToken ( ) ) ) ;
}
2012-09-05 13:37:39 +04:00
2013-08-03 09:48:28 +04:00
static
bool hasFunctionSelector ( DeclContext * ,
const llvm : : SmallVector < Expr * , 4 > & ,
LookupResult & Result ,
DeclarationNameInfo & ,
const TemplateArgumentListInfo * ,
ASTContext & , Parser & , Sema & ) {
//
// Check for lookup failure.
//
if ( Result . empty ( ) )
return false ;
if ( Result . isSingleResult ( ) )
return isa < FunctionDecl > ( Result . getFoundDecl ( ) ) ;
// We have many - those must be functions.
return true ;
}
2013-04-05 17:50:01 +04:00
bool LookupHelper : : hasFunction ( const clang : : Decl * scopeDecl ,
llvm : : StringRef funcName ) const {
//FIXME: remore code duplication with findFunctionArgs() and friends.
assert ( scopeDecl & & " Decl cannot be null " ) ;
//
// Our return value.
//
FunctionDecl * TheDecl = 0 ;
//
// Some utilities.
//
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
ASTContext & Context = S . getASTContext ( ) ;
2013-08-03 09:48:28 +04:00
2013-04-05 17:50:01 +04:00
//
2013-08-03 09:48:28 +04:00
// Convert the passed decl into a nested name specifier,
// a scope spec, and a decl context.
2013-04-05 17:50:01 +04:00
//
2013-08-03 09:48:28 +04:00
// Do this 'early' to save on the expansive parser setup,
// in case of failure.
2013-04-05 17:50:01 +04:00
//
2013-08-03 09:48:28 +04:00
CXXScopeSpec SS ;
DeclContext * foundDC = getContextAndSpec ( SS , scopeDecl , Context , S ) ;
if ( ! foundDC ) return 0 ;
ParserStateRAII ResetParserState ( P ) ;
llvm : : SmallVector < Expr * , 4 > GivenArgs ;
return findFunction ( foundDC , SS ,
funcName , GivenArgs ,
Context , P , S , hasFunctionSelector ) ;
2013-04-05 17:50:01 +04:00
}
2012-09-05 13:37:39 +04:00
} // end namespace cling