2012-09-05 13:37:39 +04:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author: Vassil Vassilev <vvasilev@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/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 ;
}
} ;
2013-08-25 08:19:24 +04:00
///\brief Class to help with the custom allocation of clang::Expr
///
struct ExprAlloc {
char fBuffer [ sizeof ( clang : : OpaqueValueExpr ) ] ;
} ;
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-20 01:19:52 +04:00
if ( typeName . empty ( ) ) return 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.
//
2013-11-07 00:33:57 +04:00
clang : : ParsedAttributes Attrs ( P . getAttrFactory ( ) ) ;
TypeResult Res ( P . ParseTypeName ( 0 , Declarator : : TypeNameContext , clang : : AS_none ,
0 , & Attrs ) ) ;
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.
//
2013-08-20 01:19:52 +04:00
if ( Name . empty ( ) ) return 0 ;
2012-12-01 11:22:56 +04:00
// 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-11-06 07:47:48 +04:00
const ValueDecl * LookupHelper : : findDataMember ( const clang : : Decl * scopeDecl ,
llvm : : StringRef dataName
) const {
// Lookup a data member based on its Decl(Context), name.
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
Preprocessor & PP = S . getPreprocessor ( ) ;
IdentifierInfo * dataII = & PP . getIdentifierTable ( ) . get ( dataName ) ;
DeclarationName decl_name ( dataII ) ;
const clang : : DeclContext * dc = llvm : : cast < clang : : DeclContext > ( scopeDecl ) ;
DeclContext : : lookup_result lookup = const_cast < clang : : DeclContext * > ( dc ) - > lookup ( decl_name ) ;
for ( DeclContext : : lookup_iterator I = lookup . begin ( ) , E = lookup . end ( ) ;
I ! = E ; + + I ) {
const ValueDecl * result = dyn_cast < ValueDecl > ( * I ) ;
2013-11-22 23:09:17 +04:00
if ( result & & ! isa < FunctionDecl > ( result ) )
2013-11-06 07:47:48 +04:00
return result ;
}
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 ;
}
2013-11-13 17:51:48 +04:00
static bool FuncArgTypesMatch ( const ASTContext & C ,
2013-09-25 17:43:26 +04:00
const llvm : : SmallVector < Expr * , 4 > & GivenArgs ,
2013-08-12 21:32:16 +04:00
const FunctionProtoType * FPT ) {
// FIXME: What if FTP->arg_size() != GivenArgTypes.size()?
FunctionProtoType : : arg_type_iterator ATI = FPT - > arg_type_begin ( ) ;
FunctionProtoType : : arg_type_iterator E = FPT - > arg_type_end ( ) ;
2013-09-25 17:43:26 +04:00
llvm : : SmallVector < Expr * , 4 > : : const_iterator GAI = GivenArgs . begin ( ) ;
2013-08-12 21:32:16 +04:00
for ( ; ATI & & ( ATI ! = E ) ; + + ATI , + + GAI ) {
2013-09-25 17:43:26 +04:00
if ( ( * GAI ) - > isLValue ( ) ) {
// If the user specified a reference we may have transform it into
// an LValue non reference (See getExprProto) to have it in a form
// useful for the lookup. So we are a bit sloppy per se here (maybe)
const ReferenceType * RefType = ( * ATI ) - > getAs < ReferenceType > ( ) ;
if ( RefType ) {
if ( ! C . hasSameType ( RefType - > getPointeeType ( ) , ( * GAI ) - > getType ( ) ) )
return false ;
} else if ( ! C . hasSameType ( * ATI , ( * GAI ) - > getType ( ) ) ) {
return false ;
}
} else if ( ! C . hasSameType ( * ATI , ( * GAI ) - > getType ( ) ) ) {
2013-08-12 21:32:16 +04:00
return false ;
}
}
return true ;
}
static bool IsOverload ( const ASTContext & C ,
const TemplateArgumentListInfo * FuncTemplateArgs ,
2013-09-25 17:43:26 +04:00
const llvm : : SmallVector < Expr * , 4 > & GivenArgs ,
2013-08-12 22:30:55 +04:00
const FunctionDecl * FD ) {
2013-08-12 21:32:16 +04:00
//FunctionTemplateDecl* FTD = FD->getDescribedFunctionTemplate();
QualType FQT = C . getCanonicalType ( FD - > getType ( ) ) ;
if ( llvm : : isa < FunctionNoProtoType > ( FQT . getTypePtr ( ) ) ) {
// A K&R-style function (no prototype), is considered to match the args.
return false ;
}
const FunctionProtoType * FPT = llvm : : cast < FunctionProtoType > ( FQT ) ;
2013-09-25 17:43:26 +04:00
if ( ( GivenArgs . size ( ) ! = FPT - > getNumArgs ( ) ) | |
2013-08-12 21:32:16 +04:00
//(GivenArgsAreEllipsis != FPT->isVariadic()) ||
2013-09-25 17:43:26 +04:00
! FuncArgTypesMatch ( C , GivenArgs , FPT ) ) {
2013-08-12 21:32:16 +04:00
return true ;
}
return false ;
}
2013-08-03 09:48:28 +04:00
static
const FunctionDecl * overloadFunctionSelector ( DeclContext * foundDC ,
2013-08-06 20:06:44 +04:00
bool objectIsConst ,
2013-08-03 09:48:28 +04:00
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 : : Classification ObjExprClassification ;
if ( CXXRecordDecl * CRD = dyn_cast < CXXRecordDecl > ( foundDC ) ) {
2013-08-06 20:06:44 +04:00
if ( objectIsConst )
ClassType = Context . getTypeDeclType ( CRD ) . getCanonicalType ( ) . withConst ( ) ;
else 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 ( ) ;
2013-11-04 10:07:51 +04:00
if ( TheDecl - > isTemplateInstantiation ( ) & & ! TheDecl - > isDefined ( ) )
S . InstantiateFunctionDefinition ( SourceLocation ( ) , TheDecl , true ) ;
2013-08-03 09:48:28 +04:00
}
}
return TheDecl ;
}
2013-08-12 22:30:55 +04:00
static
const FunctionDecl * matchFunctionSelector ( DeclContext * foundDC ,
bool objectIsConst ,
const llvm : : SmallVector < Expr * , 4 > & GivenArgs ,
LookupResult & Result ,
DeclarationNameInfo & FuncNameInfo ,
const TemplateArgumentListInfo * FuncTemplateArgs ,
ASTContext & Context , Parser & P , Sema & S ) {
//
// Our return value.
//
const FunctionDecl * TheDecl = overloadFunctionSelector ( foundDC , objectIsConst ,
GivenArgs , Result ,
FuncNameInfo ,
FuncTemplateArgs ,
Context , P , S ) ;
if ( TheDecl ) {
2013-11-02 03:40:29 +04:00
if ( IsOverload ( Context , FuncTemplateArgs , GivenArgs , TheDecl ) ) {
2013-08-12 22:30:55 +04:00
return 0 ;
} else {
// Double check const-ness.
if ( const clang : : CXXMethodDecl * md =
llvm : : dyn_cast < clang : : CXXMethodDecl > ( TheDecl ) ) {
if ( md - > getTypeQualifiers ( ) & clang : : Qualifiers : : Const ) {
if ( ! objectIsConst ) {
TheDecl = 0 ;
}
} else {
if ( objectIsConst ) {
TheDecl = 0 ;
}
}
}
}
}
return TheDecl ;
}
2013-08-21 06:27:35 +04:00
static bool ParseWithShortcuts ( DeclContext * foundDC , CXXScopeSpec & SS ,
llvm : : StringRef funcName ,
Parser & P , Sema & S ,
UnqualifiedId & FuncId ) {
// Use a very simple parse step that dectect whether the name search (which
// is already supposed to be an unqualified name) is a simple identifier,
// a constructor name or a destructor name. In those 3 cases, we can easily
// create the UnqualifiedId object that would have resulted from the 'real'
// parse. By using this direct creation of the UnqualifiedId, we avoid the
// 'permanent' cost associated with creating a memory buffer and the
// associated FileID.
// If the name is a template or an operator, we revert to the regular parse
// (and its associated permanent cost).
// In the operator case, the additional work is in the case of a conversion
// operator where we would need to 'quickly' parse the type itself (if want
// to avoid the permanent cost).
// In the case with the template the problem gets a bit worse as we need to
// handle potentially arbitrary spaces and ordering
// ('const int' vs 'int const', etc.)
if ( funcName . size ( ) = = 0 ) return false ;
Preprocessor & PP = S . getPreprocessor ( ) ;
// See if we can avoid creating the buffer, for now we just look for
// simple indentifier, constructor and destructor.
if ( funcName . size ( ) > 8 & & strncmp ( funcName . data ( ) , " operator " , 8 ) = = 0
& & ( funcName [ 8 ] = = ' ' | | funcName [ 8 ] = = ' * '
| | funcName [ 8 ] = = ' % ' | | funcName [ 8 ] = = ' & '
2013-08-27 07:41:45 +04:00
| | funcName [ 8 ] = = ' | ' | | funcName [ 8 ] = = ' / '
2013-08-21 06:27:35 +04:00
| | funcName [ 8 ] = = ' + ' | | funcName [ 8 ] = = ' - '
| | funcName [ 8 ] = = ' ( ' | | funcName [ 8 ] = = ' [ '
| | funcName [ 8 ] = = ' = ' | | funcName [ 8 ] = = ' ! '
| | funcName [ 8 ] = = ' < ' | | funcName [ 8 ] = = ' > '
| | funcName [ 8 ] = = ' - ' | | funcName [ 8 ] = = ' ^ ' )
) {
// We have called:
// setOperatorFunctionId (SourceLocation OperatorLoc,
// OverloadedOperatorKind Op,
// SourceLocation SymbolLocations[3])
// or
// setConversionFunctionId (SourceLocation OperatorLoc,
// ParsedType Ty, SourceLocation EndLoc)
} else if ( funcName . find ( ' < ' ) ! = StringRef : : npos ) {
// We might have a template name,
// setTemplateId (TemplateIdAnnotation *TemplateId)
// or
// setConstructorTemplateId (TemplateIdAnnotation *TemplateId)
} else if ( funcName [ 0 ] = = ' ~ ' ) {
// Destructor.
// Let's see if this is our contructor.
TagDecl * decl = llvm : : dyn_cast < TagDecl > ( foundDC ) ;
if ( decl ) {
// We have a class or struct or something.
if ( funcName . substr ( 1 ) . equals ( decl - > getName ( ) ) ) {
ParsedType PT ;
QualType QT ( decl - > getTypeForDecl ( ) , 0 ) ;
PT . set ( QT ) ;
FuncId . setDestructorName ( SourceLocation ( ) , PT , SourceLocation ( ) ) ;
return true ;
}
}
// So it starts with ~ but is not followed by the name of
// a class or at least not the one that is the declaration context,
// let's try a real parsing, to see if we can do better.
} else {
// We either have a simple type or a constructor name
TagDecl * decl = llvm : : dyn_cast < TagDecl > ( foundDC ) ;
if ( decl ) {
// We have a class or struct or something.
if ( funcName . equals ( decl - > getName ( ) ) ) {
ParsedType PT ;
QualType QT ( decl - > getTypeForDecl ( ) , 0 ) ;
PT . set ( QT ) ;
FuncId . setConstructorName ( PT , SourceLocation ( ) , SourceLocation ( ) ) ;
} else {
IdentifierInfo * TypeInfoII = & PP . getIdentifierTable ( ) . get ( funcName ) ;
FuncId . setIdentifier ( TypeInfoII , SourceLocation ( ) ) ;
}
return true ;
} else {
// We have a namespace like context, it can't be a constructor
IdentifierInfo * TypeInfoII = & PP . getIdentifierTable ( ) . get ( funcName ) ;
FuncId . setIdentifier ( TypeInfoII , SourceLocation ( ) ) ;
return true ;
}
}
//
// Setup to reparse as a type.
//
//
// Create a fake file to parse the function name.
//
2013-11-20 13:09:48 +04:00
// FIXME:, TODO: Cleanup that complete mess.
2013-08-21 06:27:35 +04:00
{
2013-11-20 13:09:48 +04:00
PP . getDiagnostics ( ) . setSuppressAllDiagnostics ( true ) ;
2013-08-21 06:27:35 +04:00
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 ( ) ) ) ;
}
//
// Parse the function name.
//
SourceLocation TemplateKWLoc ;
if ( P . ParseUnqualifiedId ( SS , /*EnteringContext*/ false ,
/*AllowDestructorName*/ true ,
/*AllowConstructorName*/ true ,
ParsedType ( ) , TemplateKWLoc ,
FuncId ) ) {
// Failed parse, cleanup.
return false ;
}
return true ;
}
2013-08-03 09:48:28 +04:00
template < typename T >
T findFunction ( DeclContext * foundDC , CXXScopeSpec & SS ,
llvm : : StringRef funcName ,
const llvm : : SmallVector < Expr * , 4 > & GivenArgs ,
2013-08-06 20:06:44 +04:00
bool objectIsConst ,
2013-08-03 09:48:28 +04:00
ASTContext & Context , Parser & P , Sema & S ,
T ( * functionSelector ) ( DeclContext * foundDC ,
2013-08-06 20:06:44 +04:00
bool objectIsConst ,
2013-08-03 09:48:28 +04:00
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.
//
// 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 ) ;
2013-08-21 06:27:35 +04:00
2013-08-03 09:48:28 +04:00
UnqualifiedId FuncId ;
From Vassil and me: move RAII out of ParseWithShortcuts().
The RAII destructs TemplateIdAnnotations that are still needed by the caller, as pointed out by valgrind:
==4595== Invalid read of size 4
==4595== at 0x1C88E9A: clang::Sema::DecomposeUnqualifiedId(clang::UnqualifiedId const&, clang::TemplateArgumentListInfo&, clang::DeclarationNameInfo&, clang::TemplateArgumentListInfo const*&) (SemaExpr.cpp:1635)
==4595== by 0x147FF03: clang::FunctionDecl const* cling::findFunction<clang::FunctionDecl const*>(clang::DeclContext*, clang::CXXScopeSpec&, llvm::StringRef, llvm::SmallVector<clang::Expr*, 4u> const&, bool, clang::ASTContext&, clang::Parser&, clang::Sema&, clang::FunctionDecl const* (*)(clang::DeclContext*, bool, llvm::SmallVector<clang::Expr*, 4u> const&, clang::LookupResult&, clang::DeclarationNameInfo&, clang::TemplateArgumentListInfo const*, clang::ASTContext&, clang::Parser&, clang::Sema&)) (LookupHelper.cpp:819)
==4595== by 0x147DE1A: cling::LookupHelper::findFunctionArgs(clang::Decl const*, llvm::StringRef, llvm::StringRef, bool) const (LookupHelper.cpp:1374)
==4595== Address 0x8013e74 is 68 bytes inside a block of size 136 free'd
==4595== at 0x402B77D: free (vg_replace_malloc.c:468)
==4595== by 0x1484A11: clang::TemplateIdAnnotation::Destroy() (ParsedTemplate.h:205)
==4595== by 0x1484979: clang::DestroyTemplateIdAnnotationsRAIIObj::~DestroyTemplateIdAnnotationsRAIIObj() (RAIIObjectsForParser.h:446)
==4595== by 0x1484914: clang::DestroyTemplateIdAnnotationsRAIIObj::~DestroyTemplateIdAnnotationsRAIIObj() (RAIIObjectsForParser.h:442)
==4595== by 0x14848F8: cling::ParserStateRAII::~ParserStateRAII() (LookupHelper.cpp:67)
==4595== by 0x147F284: cling::ParserStateRAII::~ParserStateRAII() (LookupHelper.cpp:54)
==4595== by 0x147EDB1: cling::ParseWithShortcuts(clang::DeclContext*, clang::CXXScopeSpec&, llvm::StringRef, clang::Parser&, clang::Sema&, clang::UnqualifiedId&) (LookupHelper.cpp:765)
==4595== by 0x147FE5A: clang::FunctionDecl const* cling::findFunction<clang::FunctionDecl const*>(clang::DeclContext*, clang::CXXScopeSpec&, llvm::StringRef, llvm::SmallVector<clang::Expr*, 4u> const&, bool, clang::ASTContext&, clang::Parser&, clang::Sema&, clang::FunctionDecl const* (*)(clang::DeclContext*, bool, llvm::SmallVector<clang::Expr*, 4u> const&, clang::LookupResult&, clang::DeclarationNameInfo&, clang::TemplateArgumentListInfo const*, clang::ASTContext&, clang::Parser&, clang::Sema&)) (LookupHelper.cpp:801)
==4595== by 0x147DE1A: cling::LookupHelper::findFunctionArgs(clang::Decl const*, llvm::StringRef, llvm::StringRef, bool) const (LookupHelper.cpp:1374)
2013-11-22 18:35:12 +04:00
ParserStateRAII ResetParserState ( P ) ;
2013-08-21 06:27:35 +04:00
if ( ! ParseWithShortcuts ( foundDC , SS , funcName , P , S , FuncId ) ) {
2013-08-03 09:48:28 +04:00
// 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.
2013-11-13 17:51:48 +04:00
return 0 ;
2013-08-03 09:48:28 +04:00
}
2013-08-21 06:27:35 +04:00
2013-08-03 09:48:28 +04:00
//
// Get any template args in the function name.
//
TemplateArgumentListInfo FuncTemplateArgsBuffer ;
DeclarationNameInfo FuncNameInfo ;
const TemplateArgumentListInfo * FuncTemplateArgs ;
S . DecomposeUnqualifiedId ( FuncId , FuncTemplateArgsBuffer , FuncNameInfo ,
FuncTemplateArgs ) ;
2013-08-21 06:27:35 +04:00
2013-08-03 09:48:28 +04:00
//
// 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 ) ;
2013-12-02 17:15:19 +04:00
Result . suppressDiagnostics ( ) ;
2013-08-03 09:48:28 +04:00
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.
2013-11-13 17:51:48 +04:00
return 0 ;
2013-08-03 09:48:28 +04:00
}
2013-08-21 06:27:35 +04:00
2013-08-03 09:48:28 +04:00
//
// 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.
2013-11-13 17:51:48 +04:00
return 0 ;
2013-08-03 09:48:28 +04:00
}
2013-08-06 20:06:44 +04:00
return functionSelector ( foundDC , objectIsConst , GivenArgs ,
2013-08-03 09:48:28 +04:00
Result ,
FuncNameInfo ,
FuncTemplateArgs ,
Context , P , S ) ;
}
static
2013-08-25 10:16:29 +04:00
bool getExprProto ( llvm : : SmallVector < ExprAlloc , 4 > & ExprMemory ,
llvm : : SmallVector < Expr * , 4 > & GivenArgs ,
const llvm : : SmallVector < QualType , 4 > & GivenTypes ) {
//
// Create the array of Expr from the array of Types.
//
typedef llvm : : SmallVector < QualType , 4 > : : const_iterator iterator ;
for ( iterator iter = GivenTypes . begin ( ) , end = GivenTypes . end ( ) ;
iter ! = end ;
+ + iter ) {
const clang : : QualType QT = iter - > getCanonicalType ( ) ;
{
ExprValueKind VK = VK_RValue ;
if ( QT - > getAs < LValueReferenceType > ( ) ) {
VK = VK_LValue ;
}
clang : : QualType NonRefQT ( QT . getNonReferenceType ( ) ) ;
unsigned int slot = ExprMemory . size ( ) ;
ExprMemory . resize ( slot + 1 ) ;
Expr * val = new ( & ExprMemory [ slot ] ) OpaqueValueExpr ( SourceLocation ( ) ,
NonRefQT , VK ) ;
GivenArgs . push_back ( val ) ;
}
}
return true ;
}
static
bool ParseProto ( llvm : : SmallVector < ExprAlloc , 4 > & ExprMemory ,
llvm : : SmallVector < Expr * , 4 > & GivenArgs ,
2013-08-06 20:06:44 +04:00
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
2013-09-05 00:56:42 +04:00
unsigned int nargs = 0 ;
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 ( ) ;
{
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-09-05 00:56:42 +04:00
ExprMemory . resize ( + + nargs ) ;
new ( & ExprMemory [ nargs - 1 ] ) OpaqueValueExpr ( TSI - > getTypeLoc ( ) . getLocStart ( ) ,
NonRefQT , VK ) ;
2012-09-05 13:37:39 +04:00
}
// 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
}
2013-09-05 00:56:42 +04:00
for ( unsigned int slot = 0 ; slot < nargs ; + + slot ) {
Expr * val = ( OpaqueValueExpr * ) ( & ExprMemory [ slot ] ) ;
GivenArgs . push_back ( val ) ;
}
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 ;
}
2013-11-13 17:51:48 +04:00
static
const FunctionTemplateDecl * findFunctionTemplateSelector ( DeclContext * ,
bool /* objectIsConst */ ,
const llvm : : SmallVector < Expr * , 4 > & ,
LookupResult & Result ,
DeclarationNameInfo & ,
const TemplateArgumentListInfo * ExplicitTemplateArgs ,
ASTContext & , Parser & ,
Sema & S ) {
//
// Check for lookup failure.
//
if ( Result . empty ( ) )
return 0 ;
if ( Result . isSingleResult ( ) )
return dyn_cast < FunctionTemplateDecl > ( Result . getFoundDecl ( ) ) ;
else {
for ( LookupResult : : iterator I = Result . begin ( ) , E = Result . end ( ) ;
I ! = E ; + + I ) {
NamedDecl * ND = * I ;
FunctionTemplateDecl * MethodTmpl = dyn_cast < FunctionTemplateDecl > ( ND ) ;
if ( MethodTmpl ) {
return MethodTmpl ;
}
}
return 0 ;
}
}
const FunctionTemplateDecl *
LookupHelper : : findFunctionTemplate ( const clang : : Decl * scopeDecl ,
llvm : : StringRef templateName ,
bool objectIsConst
) const {
// Lookup a function template based on its Decl(Context), name.
//FIXME: remove code duplication with findFunctionArgs() and friends.
assert ( scopeDecl & & " Decl cannot be null " ) ;
//
// Some utilities.
//
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
ASTContext & Context = S . getASTContext ( ) ;
//
// Convert the passed decl into a nested name specifier,
// a scope spec, and a decl context.
//
// 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 ;
ParserStateRAII ResetParserState ( P ) ;
llvm : : SmallVector < Expr * , 4 > GivenArgs ;
Interpreter : : PushTransactionRAII pushedT ( m_Interpreter ) ;
return findFunction ( foundDC , SS ,
templateName , GivenArgs , objectIsConst ,
Context , P , S , findFunctionTemplateSelector ) ;
}
2013-11-02 03:40:29 +04:00
static
const FunctionDecl * findAnyFunctionSelector ( DeclContext * ,
bool /* objectIsConst */ ,
const llvm : : SmallVector < Expr * , 4 > & ,
LookupResult & Result ,
DeclarationNameInfo & ,
2013-11-04 09:22:41 +04:00
const TemplateArgumentListInfo * ExplicitTemplateArgs ,
ASTContext & , Parser & , Sema & S ) {
2013-11-02 03:40:29 +04:00
//
// Check for lookup failure.
//
if ( Result . empty ( ) )
return 0 ;
if ( Result . isSingleResult ( ) )
return dyn_cast < FunctionDecl > ( Result . getFoundDecl ( ) ) ;
2013-11-04 09:22:41 +04:00
else {
NamedDecl * aResult = * ( Result . begin ( ) ) ;
FunctionDecl * res = dyn_cast < FunctionDecl > ( aResult ) ;
if ( res ) return res ;
FunctionTemplateDecl * MethodTmpl = dyn_cast < FunctionTemplateDecl > ( aResult ) ;
if ( MethodTmpl ) {
2013-11-11 22:00:39 +04:00
if ( ! ExplicitTemplateArgs | | ExplicitTemplateArgs - > size ( ) = = 0 ) {
// Not argument was specified, any instantiation will do.
if ( MethodTmpl - > spec_begin ( ) ! = MethodTmpl - > spec_end ( ) ) {
return * ( MethodTmpl - > spec_begin ( ) ) ;
}
}
2013-11-04 09:22:41 +04:00
// pick a specialization that result match the given arguments
SourceLocation loc ;
sema : : TemplateDeductionInfo Info ( loc ) ;
FunctionDecl * fdecl = 0 ;
Sema : : TemplateDeductionResult Result
= S . DeduceTemplateArguments ( MethodTmpl ,
const_cast < TemplateArgumentListInfo * > ( ExplicitTemplateArgs ) ,
fdecl ,
Info ) ;
if ( Result ) {
2013-11-11 22:00:39 +04:00
// Deduction failure.
2013-11-04 09:22:41 +04:00
return 0 ;
} else {
2013-11-13 17:51:48 +04:00
// Instantiate the function if needed.
2013-11-04 09:47:27 +04:00
if ( ! fdecl - > isDefined ( ) )
S . InstantiateFunctionDefinition ( loc , fdecl , true ) ;
2013-11-04 09:22:41 +04:00
return fdecl ;
}
}
return 0 ;
}
2013-11-02 03:40:29 +04:00
}
2013-11-04 09:22:41 +04:00
const FunctionDecl * LookupHelper : : findAnyFunction ( const clang : : Decl * scopeDecl ,
2013-11-02 03:40:29 +04:00
llvm : : StringRef funcName ,
bool objectIsConst
2013-11-06 07:47:48 +04:00
) const {
2013-11-02 03:40:29 +04:00
//FIXME: remove code duplication with findFunctionArgs() and friends.
assert ( scopeDecl & & " Decl cannot be null " ) ;
//
// Some utilities.
//
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
ASTContext & Context = S . getASTContext ( ) ;
//
// Convert the passed decl into a nested name specifier,
// a scope spec, and a decl context.
//
// 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 ;
ParserStateRAII ResetParserState ( P ) ;
llvm : : SmallVector < Expr * , 4 > GivenArgs ;
Interpreter : : PushTransactionRAII pushedT ( m_Interpreter ) ;
return findFunction ( foundDC , SS ,
funcName , GivenArgs , objectIsConst ,
Context , P , S , findAnyFunctionSelector ) ;
}
2013-08-25 10:16:29 +04:00
const FunctionDecl * LookupHelper : : findFunctionProto ( const Decl * scopeDecl ,
llvm : : StringRef funcName ,
const llvm : : SmallVector < QualType , 4 > & funcProto ,
bool objectIsConst
) const {
assert ( scopeDecl & & " Decl cannot be null " ) ;
//
// Some utilities.
//
// Use P for shortness
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
ASTContext & Context = S . getASTContext ( ) ;
//
// Convert the passed decl into a nested name specifier,
// a scope spec, and a decl context.
//
// 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 ;
llvm : : SmallVector < ExprAlloc , 4 > ExprMemory ;
llvm : : SmallVector < Expr * , 4 > GivenArgs ;
if ( ! funcProto . empty ( ) ) {
if ( ! getExprProto ( ExprMemory , GivenArgs , funcProto ) ) {
return 0 ;
}
}
//
// Parse the prototype now.
//
ParserStateRAII ResetParserState ( P ) ;
prepareForParsing ( " " , llvm : : StringRef ( " func.prototype.file " ) ) ;
Interpreter : : PushTransactionRAII pushedT ( m_Interpreter ) ;
return findFunction ( foundDC , SS ,
funcName , GivenArgs , objectIsConst ,
Context , P , S ,
overloadFunctionSelector ) ;
}
2013-08-03 09:48:28 +04:00
const FunctionDecl * LookupHelper : : findFunctionProto ( const Decl * scopeDecl ,
llvm : : StringRef funcName ,
2013-08-06 20:06:44 +04:00
llvm : : StringRef funcProto ,
bool objectIsConst
) const {
2013-08-03 09:48:28 +04:00
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 " ) ) ;
2013-08-25 08:19:24 +04:00
llvm : : SmallVector < ExprAlloc , 4 > ExprMemory ;
2013-08-03 09:48:28 +04:00
llvm : : SmallVector < Expr * , 4 > GivenArgs ;
2013-08-20 01:19:52 +04:00
if ( ! funcProto . empty ( ) ) {
2013-08-25 10:16:29 +04:00
if ( ! ParseProto ( ExprMemory , GivenArgs , Context , P , S ) ) {
2013-08-20 01:19:52 +04:00
return 0 ;
}
2012-09-05 13:37:39 +04:00
}
2013-08-03 09:48:28 +04:00
2013-08-11 19:07:39 +04:00
Interpreter : : PushTransactionRAII pushedT ( m_Interpreter ) ;
2013-08-03 09:48:28 +04:00
return findFunction ( foundDC , SS ,
2013-08-06 20:06:44 +04:00
funcName , GivenArgs , objectIsConst ,
2013-08-03 09:48:28 +04:00
Context , P , S ,
overloadFunctionSelector ) ;
}
2013-08-12 22:30:55 +04:00
const FunctionDecl * LookupHelper : : matchFunctionProto ( const Decl * scopeDecl ,
llvm : : StringRef funcName ,
llvm : : StringRef funcProto ,
bool objectIsConst
) const {
assert ( scopeDecl & & " Decl cannot be null " ) ;
//
// Some utilities.
//
// Use P for shortness
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
ASTContext & Context = S . getASTContext ( ) ;
//
// Convert the passed decl into a nested name specifier,
// a scope spec, and a decl context.
//
// 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 " ) ) ;
2013-08-25 08:19:24 +04:00
llvm : : SmallVector < ExprAlloc , 4 > ExprMemory ;
2013-08-12 22:30:55 +04:00
llvm : : SmallVector < Expr * , 4 > GivenArgs ;
2013-08-20 01:19:52 +04:00
if ( ! funcProto . empty ( ) ) {
2013-08-25 10:16:29 +04:00
if ( ! ParseProto ( ExprMemory , GivenArgs , Context , P , S ) ) {
2013-08-20 01:19:52 +04:00
return 0 ;
}
2013-08-12 22:30:55 +04:00
}
Interpreter : : PushTransactionRAII pushedT ( m_Interpreter ) ;
return findFunction ( foundDC , SS ,
funcName , GivenArgs , objectIsConst ,
Context , P , S ,
matchFunctionSelector ) ;
}
2013-08-25 10:16:29 +04:00
const FunctionDecl * LookupHelper : : matchFunctionProto ( const Decl * scopeDecl ,
llvm : : StringRef funcName ,
const llvm : : SmallVector < QualType , 4 > & funcProto ,
bool objectIsConst
) const {
assert ( scopeDecl & & " Decl cannot be null " ) ;
//
// Some utilities.
//
// Use P for shortness
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
ASTContext & Context = S . getASTContext ( ) ;
//
// Convert the passed decl into a nested name specifier,
// a scope spec, and a decl context.
//
// 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 ;
llvm : : SmallVector < ExprAlloc , 4 > ExprMemory ;
llvm : : SmallVector < Expr * , 4 > GivenArgs ;
if ( ! funcProto . empty ( ) ) {
if ( ! getExprProto ( ExprMemory , GivenArgs , funcProto ) ) {
return 0 ;
}
}
//
// Parse the prototype now.
//
ParserStateRAII ResetParserState ( P ) ;
prepareForParsing ( " " , llvm : : StringRef ( " func.prototype.file " ) ) ;
Interpreter : : PushTransactionRAII pushedT ( m_Interpreter ) ;
return findFunction ( foundDC , SS ,
funcName , GivenArgs , objectIsConst ,
Context , P , S ,
matchFunctionSelector ) ;
}
2013-08-03 09:48:28 +04:00
static
2013-08-06 20:06:44 +04:00
bool ParseArgs ( llvm : : SmallVector < Expr * , 4 > & GivenArgs ,
ASTContext & Context , Parser & P , Sema & S ) {
2013-08-03 09:48:28 +04:00
//
// Parse the arguments now.
//
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 ) ;
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 ,
2013-08-06 20:06:44 +04:00
llvm : : StringRef funcName ,
llvm : : StringRef funcArgs ,
bool objectIsConst
) 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 ;
2013-08-20 01:19:52 +04:00
if ( ! funcArgs . empty ( ) ) {
if ( ! ParseArgs ( GivenArgs , Context , P , S ) ) {
return 0 ;
}
2012-09-05 13:37:39 +04:00
}
2013-08-03 09:48:28 +04:00
2013-08-11 19:07:39 +04:00
Interpreter : : PushTransactionRAII pushedT ( m_Interpreter ) ;
2013-08-03 09:48:28 +04:00
return findFunction ( foundDC , SS ,
2013-08-06 20:06:44 +04:00
funcName , GivenArgs , objectIsConst ,
2013-08-03 09:48:28 +04:00
Context , P , S , overloadFunctionSelector ) ;
2012-09-05 13:37:39 +04:00
}
void LookupHelper : : findArgList ( llvm : : StringRef argList ,
llvm : : SmallVector < Expr * , 4 > & argExprs ) const {
2013-08-20 01:19:52 +04:00
if ( argList . empty ( ) ) return ;
2012-09-05 13:37:39 +04:00
//
// Some utilities.
//
// Use P for shortness
2013-08-20 01:19:52 +04:00
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 ;
//
// 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 ( ) ;
}
2013-08-20 01:19:52 +04:00
if ( ! code . empty ( ) ) {
//
// Create a fake file to parse the type name.
//
llvm : : MemoryBuffer * SB
= llvm : : MemoryBuffer : : getMemBufferCopy ( code . str ( ) + " \n " ,
bufferName . str ( ) ) ;
FileID FID = S . getSourceManager ( ) . createFileIDForMemBuffer ( SB ) ;
//
// 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-10-12 19:27:02 +04:00
}
2012-09-05 13:37:39 +04:00
2013-08-03 09:48:28 +04:00
static
bool hasFunctionSelector ( DeclContext * ,
2013-08-06 20:06:44 +04:00
bool /* objectIsConst */ ,
2013-08-03 09:48:28 +04:00
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 {
2013-11-01 15:08:38 +04:00
//FIXME: remove code duplication with findFunctionArgs() and friends.
2013-04-05 17:50:01 +04:00
assert ( scopeDecl & & " Decl cannot be null " ) ;
//
// 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 ;
2013-08-11 19:07:39 +04:00
Interpreter : : PushTransactionRAII pushedT ( m_Interpreter ) ;
2013-08-03 09:48:28 +04:00
return findFunction ( foundDC , SS ,
2013-08-06 20:06:44 +04:00
funcName , GivenArgs , false /* objectIsConst */ ,
2013-08-03 09:48:28 +04:00
Context , P , S , hasFunctionSelector ) ;
2013-04-05 17:50:01 +04:00
}
2012-09-05 13:37:39 +04:00
} // end namespace cling