2012-09-05 09:37:39 +00:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author: Vassil Vassilev <vvasilev@cern.ch>
2014-01-07 11:08:37 +01: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 09:37:39 +00:00
//------------------------------------------------------------------------------
# include "cling/Interpreter/LookupHelper.h"
2014-03-27 17:30:09 +01:00
# include "TransactionUnloader.h"
2013-04-03 16:25:08 +00:00
# include "cling/Interpreter/Interpreter.h"
2014-09-15 05:43:47 -05:00
# include "cling/Utils/AST.h"
2013-04-03 16:25:08 +00:00
2012-09-05 09:37:39 +00:00
# include "clang/AST/ASTContext.h"
2014-08-01 16:36:54 +02:00
# include "clang/Frontend/CompilerInstance.h"
2012-09-05 09:37:39 +00:00
# include "clang/Parse/Parser.h"
2012-11-15 20:19:21 +00:00
# include "clang/Parse/RAIIObjectsForParser.h"
2012-09-05 09:37:39 +00: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 00:48:28 -05:00
///
2012-09-05 09:37:39 +00:00
/// After a failed lookup we need to discard the remaining unparsed input,
2012-11-20 13:17:55 +00:00
/// restore the original state of the incremental parsing flag, clear any
2012-09-05 09:37:39 +00: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-15 20:19:21 +00:00
DestroyTemplateIdAnnotationsRAIIObj CleanupTemplateIds ;
2012-09-05 09:37:39 +00:00
public :
2012-11-20 13:17:55 +00:00
ParserStateRAII ( Parser & p )
2013-08-03 00:48:28 -05:00
: P ( & p ) , PP ( p . getPreprocessor ( ) ) ,
2013-02-19 09:25:04 +00:00
ResetIncrementalProcessing ( p . getPreprocessor ( )
. isIncrementalProcessingEnabled ( ) ) ,
OldSuppressAllDiagnostics ( p . getPreprocessor ( ) . getDiagnostics ( )
. getSuppressAllDiagnostics ( ) ) ,
OldSpellChecking ( p . getPreprocessor ( ) . getLangOpts ( ) . SpellChecking ) ,
CleanupTemplateIds ( p )
{
}
2012-09-05 09:37:39 +00: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.
//
2014-02-18 08:22:16 +01:00
P - > SkipUntil ( tok : : eof ) ;
2012-10-12 16:09:04 +00:00
PP . enableIncrementalProcessing ( ResetIncrementalProcessing ) ;
2014-04-01 10:51:50 +02:00
// Doesn't reset the diagnostic mappings
P - > getActions ( ) . getDiagnostics ( ) . Reset ( /*soft=*/ true ) ;
2012-09-05 09:37:39 +00:00
PP . getDiagnostics ( ) . setSuppressAllDiagnostics ( OldSuppressAllDiagnostics ) ;
const_cast < LangOptions & > ( PP . getLangOpts ( ) ) . SpellChecking =
OldSpellChecking ;
}
} ;
2013-08-24 23:19:24 -05:00
///\brief Class to help with the custom allocation of clang::Expr
///
struct ExprAlloc {
char fBuffer [ sizeof ( clang : : OpaqueValueExpr ) ] ;
} ;
2012-11-26 13:45:32 +00: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 00:48:28 -05:00
LookupHelper : : LookupHelper ( clang : : Parser * P , Interpreter * interp )
2013-04-03 16:25:08 +00:00
: m_Parser ( P ) , m_Interpreter ( interp ) { }
2012-11-26 13:45:32 +00:00
LookupHelper : : ~ LookupHelper ( ) { }
2012-10-12 15:27:02 +00:00
2014-09-15 05:16:36 -05:00
static
DeclContext * getContextAndSpec ( CXXScopeSpec & SS ,
const Decl * scopeDecl ,
ASTContext & Context , Sema & S ) ;
2014-09-11 21:54:19 -05:00
static void prepareForParsing ( Parser & P ,
const Interpreter * Interp ,
llvm : : StringRef code ,
llvm : : StringRef bufferName ,
LookupHelper : : DiagSetting diagOnOff ) {
//Parser& P = *m_Parser;
Sema & S = P . getActions ( ) ;
Preprocessor & PP = P . getPreprocessor ( ) ;
//
// Tell the diagnostic engine to ignore all diagnostics.
//
PP . getDiagnostics ( ) . setSuppressAllDiagnostics (
diagOnOff = = LookupHelper : : NoDiagnostics ) ;
//
// 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 ( ) ;
}
2014-09-12 04:20:29 -05:00
assert ( ! code . empty ( ) & & " prepareForParsing should only be called when needd " ) ;
//
// Create a fake file to parse the type name.
//
llvm : : MemoryBuffer * SB
2014-09-11 21:54:19 -05:00
= llvm : : MemoryBuffer : : getMemBufferCopy ( code . str ( ) + " \n " ,
bufferName . str ( ) ) ;
2014-09-12 04:20:29 -05:00
SourceLocation NewLoc = Interp - > getNextAvailableLoc ( ) ;
FileID FID = S . getSourceManager ( ) . createFileID ( SB , SrcMgr : : C_User ,
/*LoadedID*/ 0 ,
/*LoadedOffset*/ 0 , NewLoc ) ;
//
// 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 , NewLoc ) ;
PP . Lex ( const_cast < Token & > ( P . getCurToken ( ) ) ) ;
2014-09-11 21:54:19 -05:00
}
2014-02-19 08:31:45 +01:00
QualType LookupHelper : : findType ( llvm : : StringRef typeName ,
DiagSetting diagOnOff ) const {
2012-09-05 09:37:39 +00:00
//
// Our return value.
//
QualType TheQT ;
2013-08-19 16:19:52 -05:00
if ( typeName . empty ( ) ) return TheQT ;
2013-08-15 08:33:14 -05:00
// Could trigger deserialization of decls.
Interpreter : : PushTransactionRAII RAII ( m_Interpreter ) ;
2012-09-05 09:37:39 +00:00
// Use P for shortness
Parser & P = * m_Parser ;
2012-11-20 13:17:55 +00:00
ParserStateRAII ResetParserState ( P ) ;
2014-09-11 21:54:19 -05:00
prepareForParsing ( P , m_Interpreter ,
typeName , llvm : : StringRef ( " lookup.type.by.name.file " ) ,
2014-02-19 08:31:45 +01:00
diagOnOff ) ;
2012-09-05 09:37:39 +00:00
//
// Try parsing the type name.
//
2013-11-06 14:33:57 -06:00
clang : : ParsedAttributes Attrs ( P . getAttrFactory ( ) ) ;
TypeResult Res ( P . ParseTypeName ( 0 , Declarator : : TypeNameContext , clang : : AS_none ,
0 , & Attrs ) ) ;
2012-09-05 09:37:39 +00:00
if ( Res . isUsable ( ) ) {
// Accept it only if the whole name was parsed.
2012-09-18 11:45:00 +00:00
if ( P . NextToken ( ) . getKind ( ) = = clang : : tok : : eof ) {
2012-09-05 09:37:39 +00:00
TypeSourceInfo * TSI = 0 ;
TheQT = clang : : Sema : : GetTypeFromParser ( Res . get ( ) , & TSI ) ;
}
}
return TheQT ;
}
2014-09-15 05:16:36 -05:00
static const TagDecl * RequireCompleteDeclContext ( Sema & S ,
Preprocessor & PP ,
const TagDecl * tobeCompleted ,
LookupHelper : : DiagSetting diagOnOff )
{
// getContextAndSpec create the CXXScopeSpec and requires the scope
// to be complete, so this is exactly what we need.
bool OldSuppressAllDiagnostics ( PP . getDiagnostics ( )
. getSuppressAllDiagnostics ( ) ) ;
PP . getDiagnostics ( ) . setSuppressAllDiagnostics (
diagOnOff = = LookupHelper : : NoDiagnostics ) ;
CXXScopeSpec SS ;
ASTContext & Context = S . getASTContext ( ) ;
DeclContext * complete = getContextAndSpec ( SS , tobeCompleted , Context , S ) ;
PP . getDiagnostics ( ) . setSuppressAllDiagnostics ( OldSuppressAllDiagnostics ) ;
if ( complete ) {
const TagDecl * result = dyn_cast < TagDecl > ( complete ) ;
return result - > getDefinition ( ) ;
} else return 0 ;
}
2012-09-05 09:37:39 +00:00
const Decl * LookupHelper : : findScope ( llvm : : StringRef className ,
2014-02-19 08:31:45 +01:00
DiagSetting diagOnOff ,
2012-12-09 01:51:25 +00:00
const Type * * resultType /* = 0 */ ,
bool instantiateTemplate /*=true*/ ) const {
2014-09-15 05:16:36 -05:00
2012-09-05 09:37:39 +00: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 10:16:01 +00:00
2014-09-15 05:16:36 -05:00
// See if we can find it without a buffer and any clang parsing,
// We need to go scope by scope.
if ( 1 ) {
const clang : : DeclContext * sofar = 0 ;
const clang : : Decl * next = 0 ;
for ( size_t c = 0 , last = 0 ; c < className . size ( ) ; + + c ) {
if ( className [ c ] = = ' < ' | | className [ c ] = = ' > ' ) {
// For now we do not know how to deal with
// template instances.
break ;
}
if ( className [ c ] = = ' : ' ) {
if ( c + 2 > = className . size ( ) | | className [ c + 1 ] ! = ' : ' ) {
// Looks like an invalid name, we won't find anything.
return 0 ;
}
next = utils : : Lookup : : Named ( & S , className . substr ( last , c - last ) , sofar ) ;
if ( next & & next ! = ( void * ) - 1 ) {
// Need to handle typedef here too.
const TypedefNameDecl * typedefDecl = dyn_cast < TypedefNameDecl > ( next ) ;
if ( typedefDecl ) {
// We are stripping the typedef, this is technically incorrect,
// as the result (if resultType has been specified) will not be
// an accurate representation of the input string.
// As we strip the typedef we ought to rebuild the nested name
// specifier.
// Since we do not use this path for template handling, this
// is not relevant for ROOT itself ....
QualType T = Context . getTypedefType ( typedefDecl ) ;
const TagType * TagTy = T - > getAs < TagType > ( ) ;
if ( TagTy ) next = TagTy - > getDecl ( ) ;
}
// To use Lookup::Named we need to fit the assertion:
// ((!isa<TagDecl>(LookupCtx) || LookupCtx->isDependentContext()
// || cast<TagDecl>(LookupCtx)->isCompleteDefinition()
// || cast<TagDecl>(LookupCtx)->isBeingDefined()) &&
// "Declaration context must already be complete!"),
// function LookupQualifiedName, file SemaLookup.cpp, line 1614.
const clang : : TagDecl * tdecl = dyn_cast < TagDecl > ( next ) ;
if ( tdecl & & ! ( next = tdecl - > getDefinition ( ) ) ) {
//fprintf(stderr,"Incomplete (inner) type for %s (part %s).\n",
// className.str().c_str(),
// className.substr(last,c-last).str().c_str());
// Incomplete type we will not be able to go on.
// We always require completeness of the scope, if the caller
// want piece-meal instantiation, the calling code will need to
// split the call to findScope.
// if (instantiateTemplate) {
if ( dyn_cast < ClassTemplateSpecializationDecl > ( tdecl ) ) {
// Go back to the normal schedule since we need a valid point
// of instantiation:
// Assertion failed: (Loc.isValid() &&
// "point of instantiation must be valid!"),
// function setPointOfInstantiation, file DeclTemplate.h,
// line 1520.
// Which can happen here because the simple name maybe a
// typedef to a template (for example std::string).
break ;
}
next = RequireCompleteDeclContext ( S , PP , tdecl , diagOnOff ) ;
// } else {
// return 0;
// }
}
sofar = dyn_cast_or_null < DeclContext > ( next ) ;
} else {
sofar = 0 ;
}
if ( ! sofar ) {
// We are looking into something that is not a decl context,
// we won't find anything.
return 0 ;
}
last = c + 2 ;
+ + c ; // Consume the second ':'
} else if ( c + 1 = = className . size ( ) ) {
// End of the line.
next = utils : : Lookup : : Named ( & S , className . substr ( last , c + 1 - last ) , sofar ) ;
if ( next = = ( void * ) - 1 ) next = 0 ;
if ( next ) {
const TagDecl * tagdecl = dyn_cast < TagDecl > ( next ) ;
const TypedefNameDecl * typedefDecl = dyn_cast < TypedefNameDecl > ( next ) ;
if ( typedefDecl ) {
QualType T = Context . getTypedefType ( typedefDecl ) ;
const TagType * TagTy = T - > getAs < TagType > ( ) ;
if ( TagTy ) tagdecl = TagTy - > getDecl ( ) ;
// NOTE: Should we instantiate here? ... maybe ...
if ( tagdecl & & resultType ) * resultType = T . getTypePtr ( ) ;
} else if ( tagdecl & & resultType ) {
* resultType = tagdecl - > getTypeForDecl ( ) ;
}
// fprintf(stderr,"Short cut taken for %s.\n",className.str().c_str());
if ( tagdecl ) {
const TagDecl * defdecl = tagdecl - > getDefinition ( ) ;
if ( ! defdecl | | ! defdecl - > isCompleteDefinition ( ) ) {
// fprintf(stderr,"Incomplete type for %s.\n",className.str().c_str());
if ( instantiateTemplate ) {
if ( dyn_cast < ClassTemplateSpecializationDecl > ( tagdecl ) ) {
// Go back to the normal schedule since we need a valid point
// of instantiation:
// Assertion failed: (Loc.isValid() &&
// "point of instantiation must be valid!"),
// function setPointOfInstantiation, file DeclTemplate.h,
// line 1520.
// Which can happen here because the simple name maybe a
// typedef to a template (for example std::string).
break ;
}
return RequireCompleteDeclContext ( S , PP , tagdecl , diagOnOff ) ;
} else {
return 0 ;
}
}
return defdecl ; // now pointing to the definition.
} else if ( isa < NamespaceDecl > ( next ) ) {
return next - > getCanonicalDecl ( ) ;
} else if ( auto alias = dyn_cast < NamespaceAliasDecl > ( next ) ) {
return alias - > getNamespace ( ) - > getCanonicalDecl ( ) ;
} else {
//fprintf(stderr,"Not a scope decl for %s.\n",className.str().c_str());
// The name exist and does not point to a 'scope' decl.
return 0 ;
}
} else {
return 0 ;
}
}
}
}
2013-08-03 00:48:28 -05: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 10:16:01 +00:00
Interpreter : : PushTransactionRAII pushedT ( m_Interpreter ) ;
2012-11-20 13:17:55 +00:00
ParserStateRAII ResetParserState ( P ) ;
2014-09-11 21:54:19 -05:00
prepareForParsing ( P , m_Interpreter ,
className . str ( ) + " :: " ,
2014-02-19 08:31:45 +01:00
llvm : : StringRef ( " lookup.class.by.name.file " ) , diagOnOff ) ;
2012-09-05 09:37:39 +00:00
//
2012-10-12 16:09:04 +00:00
// Our return values.
2012-09-05 09:37:39 +00:00
//
2012-10-12 16:09:04 +00:00
const Type * TheType = 0 ;
const Type * * setResultType = & TheType ;
if ( resultType )
setResultType = resultType ;
* setResultType = 0 ;
2012-09-05 09:37:39 +00:00
//
// Prevent failing on an assert in TryAnnotateCXXScopeToken.
//
2013-08-03 00:48:28 -05: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 07:22:56 +00:00
& & ! P . getCurToken ( ) . is ( clang : : tok : : kw_decltype ) ) {
2012-09-05 09:37:39 +00:00
// error path
2014-09-15 05:16:36 -05:00
return 0 ;
2012-09-05 09:37:39 +00:00
}
//
// Try parsing the name as a nested-name-specifier.
//
2012-09-18 11:45:00 +00:00
if ( P . TryAnnotateCXXScopeToken ( false ) ) {
2012-09-05 09:37:39 +00:00
// error path
2014-09-15 05:16:36 -05:00
return 0 ;
2012-09-05 09:37:39 +00:00
}
2014-09-15 05:16:36 -05:00
Decl * TheDecl = 0 ;
2012-09-05 09:37:39 +00:00
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 11:45:00 +00:00
if ( P . NextToken ( ) . getKind ( ) = = clang : : tok : : eof ) {
2012-09-05 09:37:39 +00: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 06:48:09 +00:00
// Intentional fall-though
2012-09-05 09:37:39 +00: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 00:48:28 -05:00
QualType temp
2012-10-14 11:44:16 +00:00
= Context . getElaboratedType ( ETK_None , prefix ,
QualType ( NNS - > getAsType ( ) , 0 ) ) ;
2012-09-05 09:37:39 +00: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 16:43:35 +00:00
TheDecl = TD - > getDefinition ( ) ;
if ( ! TheDecl & & instantiateTemplate ) {
2013-04-06 16:44:22 +00:00
2012-12-09 01:51:25 +00: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 16:43:35 +00:00
TheDecl = TD - > getDefinition ( ) ;
2014-02-27 17:11:08 +01:00
if ( TheDecl - > isInvalidDecl ( ) ) {
// if the decl is invalid try to clean up
2014-03-27 17:30:09 +01:00
TransactionUnloader U ( & S , /*CodeGenerator*/ 0 ,
/*ExecutionEngine*/ 0 ) ;
U . UnloadDecl ( TheDecl ) ;
2014-02-13 16:00:30 +01:00
return 0 ;
2014-02-27 17:11:08 +01:00
}
2014-02-13 16:00:30 +01:00
} else {
// We cannot instantiate the scope: not a valid decl.
return 0 ;
2012-09-05 09:37:39 +00:00
}
}
}
}
}
break ;
case clang : : NestedNameSpecifier : : Global : {
// Name was just "::" and nothing more.
TheDecl = Context . getTranslationUnitDecl ( ) ;
}
break ;
}
return TheDecl ;
}
}
}
2012-10-26 13:32:41 +00:00
//
// Cleanup after failed parse as a nested-name-specifier.
//
2014-02-18 08:22:16 +01:00
P . SkipUntil ( clang : : tok : : eof ) ;
2014-04-01 10:51:50 +02:00
// Doesn't reset the diagnostic mappings
S . getDiagnostics ( ) . Reset ( /*soft=*/ true ) ;
2012-10-26 13:32:41 +00:00
//
// Setup to reparse as a type.
//
2013-02-19 09:25:04 +00:00
llvm : : MemoryBuffer * SB =
2013-02-19 09:28:40 +00:00
llvm : : MemoryBuffer : : getMemBufferCopy ( className . str ( ) + " \n " ,
2013-02-19 09:25:04 +00:00
" lookup.type.file " ) ;
2014-09-15 05:16:36 -05:00
SourceLocation NewLoc = m_Interpreter - > getNextAvailableLoc ( ) ;
FileID FID = S . getSourceManager ( ) . createFileID ( SB , SrcMgr : : C_User ,
/*LoadedID*/ 0 ,
/*LoadedOffset*/ 0 , NewLoc ) ;
2014-08-01 16:36:54 +02:00
PP . EnterSourceFile ( FID , /*DirLookup*/ 0 , NewLoc ) ;
2013-02-19 09:25:04 +00:00
PP . Lex ( const_cast < clang : : Token & > ( P . getCurToken ( ) ) ) ;
2012-09-05 09:37:39 +00:00
//
// Now try to parse the name as a type.
//
2012-09-18 11:45:00 +00:00
if ( P . TryAnnotateTypeOrScopeToken ( false , false ) ) {
2012-09-05 09:37:39 +00:00
// error path
2014-09-15 05:16:36 -05:00
return 0 ;
2012-09-05 09:37:39 +00:00
}
if ( P . getCurToken ( ) . getKind ( ) = = tok : : annot_typename ) {
2012-09-18 11:45:00 +00:00
ParsedType T = P . getTypeAnnotation ( const_cast < Token & > ( P . getCurToken ( ) ) ) ;
2012-09-05 09:37:39 +00:00
// Only accept the parse if we consumed all of the name.
2013-02-19 09:30:00 +00: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 09:37:39 +00:00
}
}
return TheDecl ;
}
2014-02-19 08:31:45 +01:00
const ClassTemplateDecl * LookupHelper : : findClassTemplate ( llvm : : StringRef Name ,
DiagSetting diagOnOff ) const {
2012-12-01 07:22:56 +00:00
//
// Find a class template decl given its name.
//
2013-08-19 16:19:52 -05:00
if ( Name . empty ( ) ) return 0 ;
2012-12-01 07:22:56 +00: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 ) ;
2014-09-11 21:54:19 -05:00
prepareForParsing ( P , m_Interpreter ,
Name . str ( ) ,
2014-02-19 08:31:45 +01:00
llvm : : StringRef ( " lookup.class.by.name.file " ) , diagOnOff ) ;
2012-12-01 07:22:56 +00:00
//
// Prevent failing on an assert in TryAnnotateCXXScopeToken.
//
2013-08-03 00:48:28 -05: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 07:22:56 +00: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 00:48:28 -05:00
case NestedNameSpecifier : : TypeSpecWithTemplate :
2012-12-01 07:22:56 +00: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 00:48:28 -05:00
DeclContext : : lookup_result R
2013-04-24 16:28:08 +00: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 07:22:56 +00:00
if ( theDecl )
return theDecl ;
}
}
return 0 ;
}
2013-11-05 21:47:48 -06:00
const ValueDecl * LookupHelper : : findDataMember ( const clang : : Decl * scopeDecl ,
2014-02-19 08:31:45 +01:00
llvm : : StringRef dataName ,
DiagSetting diagOnOff ) const {
2013-11-05 21:47:48 -06:00
// Lookup a data member based on its Decl(Context), name.
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
Preprocessor & PP = S . getPreprocessor ( ) ;
2014-08-03 21:05:42 -05:00
2013-11-05 21:47:48 -06:00
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 13:09:17 -06:00
if ( result & & ! isa < FunctionDecl > ( result ) )
2013-11-05 21:47:48 -06:00
return result ;
}
return 0 ;
}
2013-08-03 00:48:28 -05:00
static
DeclContext * getContextAndSpec ( CXXScopeSpec & SS ,
const Decl * scopeDecl ,
ASTContext & Context , Sema & S ) {
2012-09-05 09:37:39 +00:00
//
2013-08-03 00:48:28 -05:00
// Convert the passed decl into a nested name specifier,
// a scope spec, and a decl context.
2012-09-05 09:37:39 +00: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 00:48:28 -05:00
//
// Some validity checks on the passed decl.
//
if ( foundDC - > isDependentContext ( ) ) {
// Passed decl is a template, we cannot use it.
return 0 ;
}
2014-09-15 05:16:36 -05:00
// We pass a 'random' but valid source range.
SS . MakeTrivial ( Context , classNNS , scopeDecl - > getSourceRange ( ) ) ;
2013-08-03 00:48:28 -05:00
if ( S . RequireCompleteDeclContext ( SS , foundDC ) ) {
// Forward decl or instantiation failure, we cannot use it.
return 0 ;
}
2014-02-27 17:11:08 +01:00
if ( scopeDecl - > isInvalidDecl ( ) ) {
// if the decl is invalid try to clean up
2014-03-27 17:30:09 +01:00
TransactionUnloader U ( & S , /*CodeGenerator*/ 0 , /*ExecutionEngine*/ 0 ) ;
U . UnloadDecl ( const_cast < Decl * > ( scopeDecl ) ) ;
2014-02-13 16:00:30 +01:00
return 0 ;
2014-02-27 17:11:08 +01:00
}
2013-08-03 00:48:28 -05:00
return foundDC ;
}
2013-11-13 07:51:48 -06:00
static bool FuncArgTypesMatch ( const ASTContext & C ,
2014-04-01 17:50:31 +02:00
const llvm : : SmallVectorImpl < Expr * > & GivenArgs ,
2013-08-12 12:32:16 -05:00
const FunctionProtoType * FPT ) {
// FIXME: What if FTP->arg_size() != GivenArgTypes.size()?
2014-02-18 08:22:16 +01:00
FunctionProtoType : : param_type_iterator ATI = FPT - > param_type_begin ( ) ;
FunctionProtoType : : param_type_iterator E = FPT - > param_type_end ( ) ;
2014-04-01 17:50:31 +02:00
llvm : : SmallVectorImpl < Expr * > : : const_iterator GAI = GivenArgs . begin ( ) ;
2013-08-12 12:32:16 -05:00
for ( ; ATI & & ( ATI ! = E ) ; + + ATI , + + GAI ) {
2013-09-25 08:43:26 -05: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 12:32:16 -05:00
return false ;
}
}
return true ;
}
static bool IsOverload ( const ASTContext & C ,
const TemplateArgumentListInfo * FuncTemplateArgs ,
2014-04-01 17:50:31 +02:00
const llvm : : SmallVectorImpl < Expr * > & GivenArgs ,
2013-08-12 13:30:55 -05:00
const FunctionDecl * FD ) {
2013-08-12 12:32:16 -05: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 ) ;
2014-02-18 08:22:16 +01:00
if ( ( GivenArgs . size ( ) ! = FPT - > getNumParams ( ) ) | |
2013-08-12 12:32:16 -05:00
//(GivenArgsAreEllipsis != FPT->isVariadic()) ||
2013-09-25 08:43:26 -05:00
! FuncArgTypesMatch ( C , GivenArgs , FPT ) ) {
2013-08-12 12:32:16 -05:00
return true ;
}
return false ;
}
2013-08-03 00:48:28 -05:00
static
const FunctionDecl * overloadFunctionSelector ( DeclContext * foundDC ,
2013-08-06 11:06:44 -05:00
bool objectIsConst ,
2014-04-01 17:50:31 +02:00
const llvm : : SmallVectorImpl < Expr * > & GivenArgs ,
2013-08-03 00:48:28 -05:00
LookupResult & Result ,
DeclarationNameInfo & FuncNameInfo ,
const TemplateArgumentListInfo * FuncTemplateArgs ,
ASTContext & Context , Parser & P , Sema & S ) {
//
// Our return value.
//
FunctionDecl * TheDecl = 0 ;
2012-09-05 09:37:39 +00:00
//
2012-10-10 20:14:23 +00: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 ) ) {
2014-08-03 21:05:42 -05:00
if ( objectIsConst )
2013-08-06 11:06:44 -05:00
ClassType = Context . getTypeDeclType ( CRD ) . getCanonicalType ( ) . withConst ( ) ;
else ClassType = Context . getTypeDeclType ( CRD ) . getCanonicalType ( ) ;
2013-08-03 00:48:28 -05:00
OpaqueValueExpr ObjExpr ( SourceLocation ( ) ,
ClassType , VK_LValue ) ;
ObjExprClassification = ObjExpr . Classify ( Context ) ;
}
//
// Construct the overload candidate set.
//
2014-06-06 10:22:39 +02:00
OverloadCandidateSet Candidates ( FuncNameInfo . getLoc ( ) ,
OverloadCandidateSet : : CSK_Normal ) ;
2013-08-03 00:48:28 -05:00
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 00:07:51 -06:00
if ( TheDecl - > isTemplateInstantiation ( ) & & ! TheDecl - > isDefined ( ) )
2014-02-13 16:00:30 +01:00
S . InstantiateFunctionDefinition ( SourceLocation ( ) , TheDecl ,
true /*recursive instantiation*/ ) ;
2014-02-27 17:11:08 +01:00
if ( TheDecl - > isInvalidDecl ( ) ) {
// if the decl is invalid try to clean up
2014-03-27 17:30:09 +01:00
TransactionUnloader U ( & S , /*CodeGenerator*/ 0 , /*ExecutionEngine*/ 0 ) ;
U . UnloadDecl ( const_cast < FunctionDecl * > ( TheDecl ) ) ;
2014-02-13 16:00:30 +01:00
return 0 ;
2014-02-27 17:11:08 +01:00
}
2013-08-03 00:48:28 -05:00
}
}
return TheDecl ;
}
2013-08-12 13:30:55 -05:00
static
const FunctionDecl * matchFunctionSelector ( DeclContext * foundDC ,
bool objectIsConst ,
2014-04-01 17:50:31 +02:00
const llvm : : SmallVectorImpl < Expr * > & GivenArgs ,
2013-08-12 13:30:55 -05:00
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 ) ;
2014-08-03 21:05:42 -05:00
2013-08-12 13:30:55 -05:00
if ( TheDecl ) {
2013-11-01 18:40:29 -05:00
if ( IsOverload ( Context , FuncTemplateArgs , GivenArgs , TheDecl ) ) {
2013-08-12 13:30:55 -05: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-20 21:27:35 -05:00
static bool ParseWithShortcuts ( DeclContext * foundDC , CXXScopeSpec & SS ,
2014-02-19 08:31:45 +01:00
llvm : : StringRef funcName ,
2014-08-01 16:36:54 +02:00
Interpreter * Interp ,
2014-02-19 08:31:45 +01:00
UnqualifiedId & FuncId ,
LookupHelper : : DiagSetting diagOnOff ) {
2014-08-03 21:05:42 -05:00
2013-08-20 21:27:35 -05:00
// 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.
2014-08-03 21:05:42 -05:00
2013-08-20 21:27:35 -05:00
// If the name is a template or an operator, we revert to the regular parse
// (and its associated permanent cost).
2014-08-03 21:05:42 -05:00
2013-08-20 21:27:35 -05:00
// 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).
2014-08-03 21:05:42 -05:00
2013-08-20 21:27:35 -05:00
// 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.)
2014-08-03 21:05:42 -05:00
2014-08-01 16:36:54 +02:00
Parser & P = const_cast < Parser & > ( Interp - > getParser ( ) ) ;
Sema & S = Interp - > getSema ( ) ;
2013-08-20 21:27:35 -05:00
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.
2014-08-03 21:05:42 -05:00
2013-08-20 21:27:35 -05:00
if ( funcName . size ( ) > 8 & & strncmp ( funcName . data ( ) , " operator " , 8 ) = = 0
& & ( funcName [ 8 ] = = ' ' | | funcName [ 8 ] = = ' * '
| | funcName [ 8 ] = = ' % ' | | funcName [ 8 ] = = ' & '
2013-08-26 22:41:45 -05:00
| | funcName [ 8 ] = = ' | ' | | funcName [ 8 ] = = ' / '
2013-08-20 21:27:35 -05: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 10:09:48 +01:00
// FIXME:, TODO: Cleanup that complete mess.
2013-08-20 21:27:35 -05:00
{
2014-02-19 08:31:45 +01:00
PP . getDiagnostics ( ) . setSuppressAllDiagnostics ( diagOnOff = =
LookupHelper : : NoDiagnostics ) ;
2013-08-20 21:27:35 -05:00
llvm : : MemoryBuffer * SB
= llvm : : MemoryBuffer : : getMemBufferCopy ( funcName . str ( )
+ " \n " , " lookup.funcname.file " ) ;
2014-08-01 16:36:54 +02:00
SourceLocation NewLoc = Interp - > getNextAvailableLoc ( ) ;
2014-08-02 16:22:00 +02:00
FileID FID = S . getSourceManager ( ) . createFileID ( SB , SrcMgr : : C_User ,
/*LoadedID*/ 0 ,
/*LoadedOffset*/ 0 , NewLoc ) ;
2014-08-01 16:36:54 +02:00
PP . EnterSourceFile ( FID , /*DirLookup*/ 0 , NewLoc ) ;
2013-08-20 21:27:35 -05:00
PP . Lex ( const_cast < clang : : Token & > ( P . getCurToken ( ) ) ) ;
}
2014-08-03 21:05:42 -05:00
2013-08-20 21:27:35 -05:00
//
// 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 00:48:28 -05:00
template < typename T >
T findFunction ( DeclContext * foundDC , CXXScopeSpec & SS ,
llvm : : StringRef funcName ,
2014-04-01 17:50:31 +02:00
const llvm : : SmallVectorImpl < Expr * > & GivenArgs ,
2013-08-06 11:06:44 -05:00
bool objectIsConst ,
2014-08-01 16:36:54 +02:00
ASTContext & Context , Interpreter * Interp ,
2013-08-03 00:48:28 -05:00
T ( * functionSelector ) ( DeclContext * foundDC ,
2013-08-06 11:06:44 -05:00
bool objectIsConst ,
2014-04-01 17:50:31 +02:00
const llvm : : SmallVectorImpl < Expr * > & GivenArgs ,
2013-08-03 00:48:28 -05:00
LookupResult & Result ,
DeclarationNameInfo & FuncNameInfo ,
const TemplateArgumentListInfo * FuncTemplateArgs ,
2014-02-19 08:31:45 +01:00
ASTContext & Context , Parser & P , Sema & S ) ,
LookupHelper : : DiagSetting diagOnOff
) {
2013-08-03 00:48:28 -05:00
// 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.
//
2014-08-01 16:36:54 +02:00
Parser & P = const_cast < Parser & > ( Interp - > getParser ( ) ) ;
Sema & S = Interp - > getSema ( ) ;
2014-02-18 08:22:16 +01:00
DeclContext * OldEntity = P . getCurScope ( ) - > getEntity ( ) ;
2013-08-03 00:48:28 -05:00
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-20 21:27:35 -05:00
2013-08-03 00:48:28 -05: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 15:35:12 +01:00
ParserStateRAII ResetParserState ( P ) ;
2014-08-01 16:36:54 +02:00
if ( ! ParseWithShortcuts ( foundDC , SS , funcName , Interp , FuncId , diagOnOff ) ) {
2013-08-03 00:48:28 -05: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 07:51:48 -06:00
return 0 ;
2013-08-03 00:48:28 -05:00
}
2013-08-20 21:27:35 -05:00
2013-08-03 00:48:28 -05:00
//
// Get any template args in the function name.
//
TemplateArgumentListInfo FuncTemplateArgsBuffer ;
DeclarationNameInfo FuncNameInfo ;
const TemplateArgumentListInfo * FuncTemplateArgs ;
S . DecomposeUnqualifiedId ( FuncId , FuncTemplateArgsBuffer , FuncNameInfo ,
FuncTemplateArgs ) ;
2013-08-20 21:27:35 -05:00
2013-08-03 00:48:28 -05: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 14:15:19 +01:00
Result . suppressDiagnostics ( ) ;
2013-08-03 00:48:28 -05: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 07:51:48 -06:00
return 0 ;
2013-08-03 00:48:28 -05:00
}
2013-08-20 21:27:35 -05:00
2013-08-03 00:48:28 -05: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 07:51:48 -06:00
return 0 ;
2013-08-03 00:48:28 -05:00
}
2013-08-06 11:06:44 -05:00
return functionSelector ( foundDC , objectIsConst , GivenArgs ,
2013-08-03 00:48:28 -05:00
Result ,
FuncNameInfo ,
FuncTemplateArgs ,
Context , P , S ) ;
}
2014-09-12 06:58:37 -05:00
template < typename DigestArgsInput , typename returnType >
returnType execFindFunction ( Parser & P ,
Interpreter * Interp ,
const clang : : Decl * scopeDecl ,
llvm : : StringRef funcName ,
const typename DigestArgsInput : : ArgsInput & funcArgs ,
bool objectIsConst ,
returnType ( * functionSelector ) ( DeclContext * foundDC ,
bool objectIsConst ,
const llvm : : SmallVectorImpl < Expr * > & GivenArgs ,
LookupResult & Result ,
DeclarationNameInfo & FuncNameInfo ,
const TemplateArgumentListInfo * FuncTemplateArgs ,
ASTContext & Context , Parser & P , Sema & S ) ,
LookupHelper : : DiagSetting diagOnOff
)
2014-09-11 20:54:36 -05:00
{
assert ( scopeDecl & & " Decl cannot be null " ) ;
//
// Some utilities.
//
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 ;
2014-09-12 06:58:37 -05:00
DigestArgsInput inputEval ;
2014-09-11 20:54:36 -05:00
llvm : : SmallVector < Expr * , 4 > GivenArgs ;
2014-09-12 06:58:37 -05:00
if ( ! inputEval ( GivenArgs , funcArgs , diagOnOff , P , Interp ) ) return 0 ;
2014-09-11 20:54:36 -05:00
Interpreter : : PushTransactionRAII pushedT ( Interp ) ;
return findFunction ( foundDC , SS ,
funcName , GivenArgs , objectIsConst ,
Context , Interp , functionSelector ,
diagOnOff ) ;
}
2014-09-12 06:58:37 -05:00
struct NoParse {
2014-08-03 21:05:42 -05:00
2014-09-12 06:58:37 -05:00
typedef const char * ArgsInput ;
bool operator ( ) ( llvm : : SmallVectorImpl < Expr * > & /* GivenArgs */ ,
const ArgsInput & /* funcArgs */ ,
LookupHelper : : DiagSetting /* diagOnOff */ ,
Parser & /* P */ , const Interpreter * /* Interp */ )
{
return true ;
}
} ;
struct ExprFromTypes {
typedef llvm : : SmallVectorImpl < QualType > ArgsInput ;
llvm : : SmallVector < ExprAlloc , 4 > ExprMemory ;
bool operator ( ) ( llvm : : SmallVectorImpl < Expr * > & GivenArgs ,
const ArgsInput & GivenTypes ,
LookupHelper : : DiagSetting /* diagOnOff */ ,
Parser & /* P */ , const Interpreter * /* Interp */ ) {
if ( GivenTypes . empty ( ) ) return true ;
else return getExprProto ( GivenArgs , GivenTypes ) ;
}
bool getExprProto ( llvm : : SmallVectorImpl < Expr * > & GivenArgs ,
const llvm : : SmallVectorImpl < QualType > & GivenTypes ) {
//
// Create the array of Expr from the array of Types.
//
typedef llvm : : SmallVectorImpl < QualType > : : 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 ) ;
2013-08-25 01:16:29 -05:00
}
}
2014-09-12 06:58:37 -05:00
return true ;
2013-08-25 01:16:29 -05:00
}
2014-09-12 06:58:37 -05:00
} ;
2013-08-25 01:16:29 -05:00
2014-09-12 06:58:37 -05:00
struct ParseProto {
2013-08-03 00:48:28 -05:00
2014-09-12 06:58:37 -05:00
typedef llvm : : StringRef ArgsInput ;
llvm : : SmallVector < ExprAlloc , 4 > ExprMemory ;
bool operator ( ) ( llvm : : SmallVectorImpl < Expr * > & GivenArgs ,
const ArgsInput & funcProto ,
LookupHelper : : DiagSetting diagOnOff ,
Parser & P , const Interpreter * Interp ) {
if ( funcProto . empty ( ) ) return true ;
else return Parse ( GivenArgs , funcProto , diagOnOff , P , Interp ) ;
}
bool Parse ( llvm : : SmallVectorImpl < Expr * > & GivenArgs ,
const ArgsInput & funcProto ,
LookupHelper : : DiagSetting diagOnOff ,
Parser & P , const Interpreter * Interp ) {
//
// Parse the prototype now.
//
ParserStateRAII ResetParserState ( P ) ;
prepareForParsing ( P , Interp ,
funcProto , llvm : : StringRef ( " func.prototype.file " ) , diagOnOff ) ;
unsigned int nargs = 0 ;
while ( P . getCurToken ( ) . isNot ( tok : : eof ) ) {
TypeResult Res ( P . ParseTypeName ( ) ) ;
if ( ! Res . isUsable ( ) ) {
// Bad parse, done.
return false ;
2012-10-10 22:55:40 +00:00
}
2014-09-12 06:58:37 -05:00
TypeSourceInfo * TSI = 0 ;
clang : : QualType QT = clang : : Sema : : GetTypeFromParser ( Res . get ( ) , & TSI ) ;
QT = QT . getCanonicalType ( ) ;
{
ExprValueKind VK = VK_RValue ;
if ( QT - > getAs < LValueReferenceType > ( ) ) {
VK = VK_LValue ;
}
clang : : QualType NonRefQT ( QT . getNonReferenceType ( ) ) ;
ExprMemory . resize ( + + nargs ) ;
new ( & ExprMemory [ nargs - 1 ] ) OpaqueValueExpr ( TSI - > getTypeLoc ( ) . getLocStart ( ) ,
NonRefQT , VK ) ;
}
// Type names should be comma separated.
// FIXME: Here if we have type followed by name won't work. Eg int f, ...
if ( ! P . getCurToken ( ) . is ( clang : : tok : : comma ) ) {
break ;
}
// Eat the comma.
P . ConsumeToken ( ) ;
2012-09-05 09:37:39 +00:00
}
2014-09-12 06:58:37 -05:00
for ( unsigned int slot = 0 ; slot < nargs ; + + slot ) {
Expr * val = ( OpaqueValueExpr * ) ( & ExprMemory [ slot ] ) ;
GivenArgs . push_back ( val ) ;
2012-09-05 09:37:39 +00:00
}
2014-09-12 06:58:37 -05:00
if ( P . getCurToken ( ) . isNot ( tok : : eof ) ) {
// We did not consume all of the prototype, bad parse.
return false ;
}
//
// Cleanup after prototype parse.
//
P . SkipUntil ( clang : : tok : : eof ) ;
// Doesn't reset the diagnostic mappings
Sema & S = P . getActions ( ) ;
S . getDiagnostics ( ) . Reset ( /*soft=*/ true ) ;
2013-08-03 00:48:28 -05:00
2014-09-12 06:58:37 -05:00
return true ;
}
} ;
2013-08-03 00:48:28 -05:00
2013-11-13 07:51:48 -06:00
static
const FunctionTemplateDecl * findFunctionTemplateSelector ( DeclContext * ,
bool /* objectIsConst */ ,
2014-04-01 17:50:31 +02:00
const llvm : : SmallVectorImpl < Expr * > & ,
2013-11-13 07:51:48 -06:00
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 ,
2014-02-19 08:31:45 +01:00
DiagSetting diagOnOff ,
bool objectIsConst ) const {
2013-11-13 07:51:48 -06:00
// Lookup a function template based on its Decl(Context), name.
2014-09-12 06:58:37 -05:00
return execFindFunction < NoParse > ( * m_Parser , m_Interpreter ,
scopeDecl ,
templateName , " " ,
objectIsConst ,
findFunctionTemplateSelector ,
diagOnOff ) ;
2013-11-13 07:51:48 -06:00
}
2013-11-01 18:40:29 -05:00
static
const FunctionDecl * findAnyFunctionSelector ( DeclContext * ,
bool /* objectIsConst */ ,
2014-04-01 17:50:31 +02:00
const llvm : : SmallVectorImpl < Expr * > & ,
2013-11-01 18:40:29 -05:00
LookupResult & Result ,
DeclarationNameInfo & ,
2013-11-03 23:22:41 -06:00
const TemplateArgumentListInfo * ExplicitTemplateArgs ,
ASTContext & , Parser & , Sema & S ) {
2013-11-01 18:40:29 -05:00
//
// Check for lookup failure.
//
if ( Result . empty ( ) )
return 0 ;
if ( Result . isSingleResult ( ) )
return dyn_cast < FunctionDecl > ( Result . getFoundDecl ( ) ) ;
2013-11-03 23:22:41 -06: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 12:00:39 -06: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-03 23:22:41 -06: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 12:00:39 -06:00
// Deduction failure.
2013-11-03 23:22:41 -06:00
return 0 ;
} else {
2013-11-13 07:51:48 -06:00
// Instantiate the function if needed.
2013-11-03 23:47:27 -06:00
if ( ! fdecl - > isDefined ( ) )
2014-02-13 16:00:30 +01:00
S . InstantiateFunctionDefinition ( loc , fdecl ,
true /*recursive instantiation*/ ) ;
2014-02-27 17:11:08 +01:00
if ( fdecl - > isInvalidDecl ( ) ) {
// if the decl is invalid try to clean up
2014-03-27 17:30:09 +01:00
TransactionUnloader U ( & S , /*CodeGenerator*/ 0 , /*ExecutionEngine*/ 0 ) ;
U . UnloadDecl ( fdecl ) ;
2014-02-13 16:00:30 +01:00
return 0 ;
2014-02-27 17:11:08 +01:00
}
2013-11-03 23:22:41 -06:00
return fdecl ;
}
}
return 0 ;
}
2013-11-01 18:40:29 -05:00
}
2013-11-03 23:22:41 -06:00
const FunctionDecl * LookupHelper : : findAnyFunction ( const clang : : Decl * scopeDecl ,
2013-11-01 18:40:29 -05:00
llvm : : StringRef funcName ,
2014-02-19 08:31:45 +01:00
DiagSetting diagOnOff ,
bool objectIsConst ) const {
2013-11-01 18:40:29 -05:00
2014-09-12 06:58:37 -05:00
return execFindFunction < NoParse > ( * m_Parser , m_Interpreter ,
scopeDecl ,
funcName , " " ,
objectIsConst ,
findAnyFunctionSelector ,
diagOnOff ) ;
2013-11-01 18:40:29 -05:00
}
2014-02-19 08:31:45 +01:00
const FunctionDecl *
LookupHelper : : findFunctionProto ( const Decl * scopeDecl ,
llvm : : StringRef funcName ,
2014-04-01 17:50:31 +02:00
const llvm : : SmallVectorImpl < QualType > & funcProto ,
2014-02-19 08:31:45 +01:00
DiagSetting diagOnOff , bool objectIsConst ) const {
2013-08-25 01:16:29 -05:00
assert ( scopeDecl & & " Decl cannot be null " ) ;
2014-09-12 06:58:37 -05:00
return execFindFunction < ExprFromTypes > ( * m_Parser , m_Interpreter ,
scopeDecl ,
funcName ,
funcProto ,
objectIsConst ,
overloadFunctionSelector ,
diagOnOff ) ;
2013-08-25 01:16:29 -05:00
}
2014-08-03 21:05:42 -05:00
2013-08-03 00:48:28 -05:00
const FunctionDecl * LookupHelper : : findFunctionProto ( const Decl * scopeDecl ,
llvm : : StringRef funcName ,
2013-08-06 11:06:44 -05:00
llvm : : StringRef funcProto ,
2014-02-19 08:31:45 +01:00
DiagSetting diagOnOff ,
bool objectIsConst ) const {
2013-08-03 00:48:28 -05:00
assert ( scopeDecl & & " Decl cannot be null " ) ;
2014-09-12 06:58:37 -05:00
return execFindFunction < ParseProto > ( * m_Parser , m_Interpreter ,
scopeDecl ,
funcName ,
funcProto ,
objectIsConst ,
overloadFunctionSelector ,
diagOnOff ) ;
2013-08-03 00:48:28 -05:00
}
2014-02-19 08:31:45 +01:00
const FunctionDecl *
LookupHelper : : matchFunctionProto ( const Decl * scopeDecl ,
llvm : : StringRef funcName ,
llvm : : StringRef funcProto ,
DiagSetting diagOnOff ,
bool objectIsConst ) const {
2013-08-12 13:30:55 -05:00
assert ( scopeDecl & & " Decl cannot be null " ) ;
2014-09-12 06:58:37 -05:00
return execFindFunction < ParseProto > ( * m_Parser , m_Interpreter ,
scopeDecl ,
funcName ,
funcProto ,
objectIsConst ,
matchFunctionSelector ,
diagOnOff ) ;
2013-08-12 13:30:55 -05:00
}
2014-02-19 08:31:45 +01:00
const FunctionDecl *
LookupHelper : : matchFunctionProto ( const Decl * scopeDecl ,
llvm : : StringRef funcName ,
2014-04-01 17:50:31 +02:00
const llvm : : SmallVectorImpl < QualType > & funcProto ,
2014-02-19 08:31:45 +01:00
DiagSetting diagOnOff ,
bool objectIsConst ) const {
2013-08-25 01:16:29 -05:00
assert ( scopeDecl & & " Decl cannot be null " ) ;
2014-08-03 21:05:42 -05:00
2014-09-12 06:58:37 -05:00
return execFindFunction < ExprFromTypes > ( * m_Parser , m_Interpreter ,
scopeDecl ,
funcName ,
funcProto ,
objectIsConst ,
matchFunctionSelector ,
diagOnOff ) ;
}
2014-08-03 21:05:42 -05:00
2014-09-12 06:58:37 -05:00
struct ParseArgs {
typedef llvm : : StringRef ArgsInput ;
2014-08-03 21:05:42 -05:00
2013-08-25 01:16:29 -05:00
llvm : : SmallVector < ExprAlloc , 4 > ExprMemory ;
2014-08-03 21:05:42 -05:00
2014-09-12 06:58:37 -05:00
bool operator ( ) ( llvm : : SmallVectorImpl < Expr * > & GivenArgs ,
const ArgsInput & funcArgs ,
LookupHelper : : DiagSetting diagOnOff ,
Parser & P , const Interpreter * Interp ) {
2014-08-03 21:05:42 -05:00
2014-09-12 06:58:37 -05:00
if ( funcArgs . empty ( ) ) return true ;
else return Parse ( GivenArgs , funcArgs , diagOnOff , P , Interp ) ;
}
bool Parse ( llvm : : SmallVectorImpl < Expr * > & GivenArgs ,
2014-09-11 21:54:19 -05:00
llvm : : StringRef funcArgs ,
LookupHelper : : DiagSetting diagOnOff ,
Parser & P , const Interpreter * Interp ) {
2013-08-03 00:48:28 -05:00
2014-09-12 06:58:37 -05:00
//
// Parse the arguments now.
//
2013-08-03 00:48:28 -05:00
2014-11-20 11:16:15 +01:00
Interpreter : : PushTransactionRAII TforDeser ( Interp ) ;
2014-09-12 06:58:37 -05:00
ParserStateRAII ResetParserState ( P ) ;
prepareForParsing ( P , Interp ,
funcArgs , llvm : : StringRef ( " func.args.file " ) , diagOnOff ) ;
2014-09-11 21:54:19 -05:00
2014-09-12 06:58:37 -05:00
Sema & S = P . getActions ( ) ;
ASTContext & Context = S . getASTContext ( ) ;
2014-09-11 21:54:19 -05:00
2014-09-12 06:58:37 -05:00
PrintingPolicy Policy ( Context . getPrintingPolicy ( ) ) ;
Policy . SuppressTagKeyword = true ;
Policy . SuppressUnwrittenScope = true ;
Policy . SuppressInitializers = true ;
Policy . AnonymousTagLocations = false ;
std : : string proto ;
{
bool first_time = true ;
while ( P . getCurToken ( ) . isNot ( tok : : eof ) ) {
ExprResult Res = P . ParseAssignmentExpression ( ) ;
if ( Res . isUsable ( ) ) {
Expr * expr = Res . get ( ) ;
GivenArgs . push_back ( expr ) ;
if ( first_time ) {
first_time = false ;
}
else {
proto + = ' , ' ;
}
std : : string empty ;
llvm : : raw_string_ostream tmp ( empty ) ;
expr - > printPretty ( tmp , /*PrinterHelper=*/ 0 , Policy ,
/*Indentation=*/ 0 ) ;
proto + = tmp . str ( ) ;
2012-09-05 09:37:39 +00:00
}
2014-09-12 06:58:37 -05:00
if ( ! P . getCurToken ( ) . is ( tok : : comma ) ) {
break ;
2012-10-10 20:14:23 +00:00
}
2014-09-12 06:58:37 -05:00
P . ConsumeToken ( ) ;
2012-09-05 09:37:39 +00:00
}
}
2014-09-12 06:58:37 -05: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 ) ;
// Doesn't reset the diagnostic mappings
S . getDiagnostics ( ) . Reset ( /*soft=*/ true ) ;
return true ;
2012-09-05 09:37:39 +00:00
}
2014-09-12 06:58:37 -05:00
} ;
2012-09-05 09:37:39 +00:00
2014-02-19 08:31:45 +01:00
const FunctionDecl *
LookupHelper : : findFunctionArgs ( const Decl * scopeDecl ,
llvm : : StringRef funcName ,
llvm : : StringRef funcArgs ,
DiagSetting diagOnOff ,
bool objectIsConst ) const {
2013-08-03 00:48:28 -05:00
assert ( scopeDecl & & " Decl cannot be null " ) ;
2012-10-12 16:09:04 +00:00
2014-09-12 06:58:37 -05:00
return execFindFunction < ParseArgs > ( * m_Parser , m_Interpreter ,
scopeDecl ,
funcName ,
funcArgs ,
objectIsConst ,
overloadFunctionSelector ,
diagOnOff ) ;
2012-09-05 09:37:39 +00:00
}
void LookupHelper : : findArgList ( llvm : : StringRef argList ,
2014-04-01 17:50:31 +02:00
llvm : : SmallVectorImpl < Expr * > & argExprs ,
2014-02-19 08:31:45 +01:00
DiagSetting diagOnOff ) const {
2013-08-19 16:19:52 -05:00
if ( argList . empty ( ) ) return ;
2012-09-05 09:37:39 +00:00
//
// Some utilities.
//
// Use P for shortness
2014-08-03 21:05:42 -05:00
Parser & P = * m_Parser ;
2012-11-20 13:17:55 +00:00
ParserStateRAII ResetParserState ( P ) ;
2014-09-11 21:54:19 -05:00
prepareForParsing ( P , m_Interpreter ,
argList , llvm : : StringRef ( " arg.list.file " ) , diagOnOff ) ;
2012-10-14 11:44:16 +00:00
//
2012-09-05 09:37:39 +00:00
// Parse the arguments now.
//
{
bool hasUnusableResult = false ;
while ( P . getCurToken ( ) . isNot ( tok : : eof ) ) {
2012-09-18 11:45:00 +00:00
ExprResult Res = P . ParseAssignmentExpression ( ) ;
2012-09-05 09:37:39 +00:00
if ( Res . isUsable ( ) ) {
2014-06-06 10:23:36 +02:00
argExprs . push_back ( Res . get ( ) ) ;
2012-09-05 09:37:39 +00:00
}
else {
hasUnusableResult = true ;
break ;
}
if ( ! P . getCurToken ( ) . is ( tok : : comma ) ) {
break ;
}
2012-09-18 11:45:00 +00:00
P . ConsumeToken ( ) ;
2012-09-05 09:37:39 +00:00
}
if ( hasUnusableResult )
// if one of the arguments is not usable return empty.
argExprs . clear ( ) ;
}
}
2013-08-03 00:48:28 -05:00
static
bool hasFunctionSelector ( DeclContext * ,
2013-08-06 11:06:44 -05:00
bool /* objectIsConst */ ,
2014-04-01 17:50:31 +02:00
const llvm : : SmallVectorImpl < Expr * > & ,
2013-08-03 00:48:28 -05:00
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 13:50:01 +00:00
bool LookupHelper : : hasFunction ( const clang : : Decl * scopeDecl ,
2014-02-19 08:31:45 +01:00
llvm : : StringRef funcName ,
DiagSetting diagOnOff ) const {
2013-04-05 13:50:01 +00:00
2014-09-12 06:58:37 -05:00
return execFindFunction < NoParse > ( * m_Parser , m_Interpreter ,
scopeDecl ,
funcName , " " ,
false /* objectIsConst */ ,
hasFunctionSelector ,
diagOnOff ) ;
2013-04-05 13:50:01 +00:00
}
2012-09-05 09:37:39 +00:00
} // end namespace cling