2012-09-05 09:37:39 +00:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id: AST.cpp 45014 2012-07-11 20:31:42Z vvassilev $
// author: Vassil Vassilev <vvasilev@cern.ch>
//------------------------------------------------------------------------------
# include "cling/Interpreter/LookupHelper.h"
2013-04-03 16:25:08 +00:00
# include "cling/Interpreter/Interpreter.h"
2012-09-05 09:37:39 +00:00
# include "clang/AST/ASTContext.h"
# 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.
///
/// 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-02-19 09:25:04 +00:00
: P ( & p ) , PP ( p . getPreprocessor ( ) ) ,
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.
//
2012-09-18 11:45:00 +00:00
P - > SkipUntil ( tok : : eof , /*StopAtSemi*/ false , /*DontConsume*/ false ,
/*StopAtCodeCompletion*/ false ) ;
2012-10-12 16:09:04 +00:00
PP . enableIncrementalProcessing ( ResetIncrementalProcessing ) ;
2012-10-14 11:44:16 +00:00
P - > getActions ( ) . getDiagnostics ( ) . Reset ( ) ;
2012-09-05 09:37:39 +00:00
PP . getDiagnostics ( ) . setSuppressAllDiagnostics ( OldSuppressAllDiagnostics ) ;
const_cast < LangOptions & > ( PP . getLangOpts ( ) ) . SpellChecking =
OldSpellChecking ;
}
} ;
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-04-03 16:25:08 +00:00
LookupHelper : : LookupHelper ( clang : : Parser * P , Interpreter * interp )
: m_Parser ( P ) , m_Interpreter ( interp ) { }
2012-11-26 13:45:32 +00:00
LookupHelper : : ~ LookupHelper ( ) { }
2012-10-12 15:27:02 +00:00
2012-09-05 09:37:39 +00:00
QualType LookupHelper : : findType ( llvm : : StringRef typeName ) const {
//
// Our return value.
//
QualType TheQT ;
// Use P for shortness
Parser & P = * m_Parser ;
2012-11-20 13:17:55 +00:00
ParserStateRAII ResetParserState ( P ) ;
2012-10-12 15:27:02 +00:00
prepareForParsing ( typeName , llvm : : StringRef ( " lookup.type.by.name.file " ) ) ;
2012-09-05 09:37:39 +00:00
//
// Try parsing the type name.
//
2012-09-18 11:45:00 +00:00
TypeResult Res ( P . ParseTypeName ( ) ) ;
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 ;
}
const Decl * LookupHelper : : findScope ( llvm : : StringRef className ,
2012-12-09 01:51:25 +00:00
const Type * * resultType /* = 0 */ ,
bool instantiateTemplate /*=true*/ ) const {
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 ( ) ;
2012-11-20 13:17:55 +00:00
ParserStateRAII ResetParserState ( P ) ;
2012-10-12 16:09:04 +00:00
prepareForParsing ( className . str ( ) + " :: " ,
llvm : : StringRef ( " lookup.class.by.name.file " ) ) ;
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 ;
const Decl * TheDecl = 0 ;
2012-09-05 09:37:39 +00:00
//
// Prevent failing on an assert in TryAnnotateCXXScopeToken.
//
2012-12-01 07:22:56 +00: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 ) )
& & ! P . getCurToken ( ) . is ( clang : : tok : : kw_decltype ) ) {
2012-09-05 09:37:39 +00:00
// error path
return TheDecl ;
}
//
// 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
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 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 ) {
2012-10-14 11:44:16 +00:00
QualType temp
= 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 ) {
2012-12-09 01:51:25 +00:00
if ( instantiateTemplate ) {
2013-04-03 16:25:08 +00:00
// Here we might not have an active transaction to handle
// the caused instantiation decl.
Interpreter : : PushTransactionRAII pushedT ( m_Interpreter ) ;
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.
TagDecl * Def = TD - > getDefinition ( ) ;
if ( Def ) {
TheDecl = Def ;
}
2012-09-05 09:37:39 +00:00
}
2012-12-09 01:51:25 +00:00
} else {
// The user just want to see if the template had
// already been instantiate and did not mean to force
// one.
TheDecl = TD - > getDefinition ( ) ;
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.
//
P . SkipUntil ( clang : : tok : : eof , /*StopAtSemi*/ false , /*DontConsume*/ false ,
/*StopAtCodeCompletion*/ false ) ;
S . getDiagnostics ( ) . Reset ( ) ;
//
// 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 " ) ;
clang : : FileID FID = S . getSourceManager ( ) . createFileIDForMemBuffer ( SB ) ;
PP . EnterSourceFile ( FID , 0 , clang : : SourceLocation ( ) ) ;
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
return TheDecl ;
}
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 ;
}
2012-12-01 07:22:56 +00:00
const ClassTemplateDecl * LookupHelper : : findClassTemplate ( llvm : : StringRef Name ) const {
//
// Find a class template decl given its name.
//
// Humm ... this seems to do the trick ... or does it? or is there a better way?
// Use P for shortness
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
ASTContext & Context = S . getASTContext ( ) ;
ParserStateRAII ResetParserState ( P ) ;
prepareForParsing ( Name . str ( ) ,
llvm : : StringRef ( " lookup.class.by.name.file " ) ) ;
//
// Prevent failing on an assert in TryAnnotateCXXScopeToken.
//
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 ) )
& & ! 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 :
case NestedNameSpecifier : : TypeSpecWithTemplate :
{
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.
for ( DeclContext : : lookup_result R
= where - > lookup ( P . getCurToken ( ) . getIdentifierInfo ( ) ) ;
R . first ! = R . second ; + + R . first ) {
ClassTemplateDecl * theDecl = dyn_cast < ClassTemplateDecl > ( ( * R . first ) ) ;
if ( theDecl )
return theDecl ;
}
}
return 0 ;
}
2012-09-05 09:37:39 +00:00
const FunctionDecl * LookupHelper : : findFunctionProto ( const Decl * scopeDecl ,
llvm : : StringRef funcName ,
llvm : : StringRef funcProto ) const {
2012-10-14 14:43:29 +00:00
assert ( scopeDecl & & " Decl cannot be null " ) ;
2012-09-05 09:37:39 +00:00
//
// Our return value.
//
FunctionDecl * TheDecl = 0 ;
//
// Some utilities.
//
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
Preprocessor & PP = S . getPreprocessor ( ) ;
ASTContext & Context = S . getASTContext ( ) ;
2012-11-20 13:17:55 +00:00
ParserStateRAII ResetParserState ( P ) ;
2012-10-12 16:09:04 +00:00
prepareForParsing ( funcProto , llvm : : StringRef ( " func.prototype.file " ) ) ;
2012-09-05 09:37:39 +00:00
//
// Get the DeclContext we will search for the function.
//
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 ) ) ;
//
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 * ObjExpr = 0 ;
Expr : : Classification ObjExprClassification ;
if ( CXXRecordDecl * CRD = dyn_cast < CXXRecordDecl > ( foundDC ) ) {
ClassType = Context . getTypeDeclType ( CRD ) . getCanonicalType ( ) ;
ObjExpr = new ( Context ) OpaqueValueExpr ( SourceLocation ( ) ,
ClassType , VK_LValue ) ;
ObjExprClassification = ObjExpr - > Classify ( Context ) ;
//GivenArgTypes.insert(GivenArgTypes.begin(), ClassType);
//GivenArgs.insert(GivenArgs.begin(), ObjExpr);
}
//
2012-09-05 09:37:39 +00:00
// Parse the prototype now.
//
llvm : : SmallVector < QualType , 4 > GivenArgTypes ;
llvm : : SmallVector < Expr * , 4 > GivenArgs ;
while ( P . getCurToken ( ) . isNot ( tok : : eof ) ) {
2012-09-18 11:45:00 +00:00
TypeResult Res ( P . ParseTypeName ( ) ) ;
2012-09-05 09:37:39 +00:00
if ( ! Res . isUsable ( ) ) {
// Bad parse, done.
return TheDecl ;
}
TypeSourceInfo * TSI = 0 ;
2012-11-30 22:42:53 +00:00
clang : : QualType QT = clang : : Sema : : GetTypeFromParser ( Res . get ( ) , & TSI ) ;
2012-09-05 09:37:39 +00:00
QT = QT . getCanonicalType ( ) ;
GivenArgTypes . push_back ( QT ) ;
{
2012-10-10 22:55:40 +00:00
ExprValueKind VK = VK_RValue ;
if ( QT - > getAs < LValueReferenceType > ( ) ) {
VK = VK_LValue ;
}
2012-09-05 09:37:39 +00:00
clang : : QualType NonRefQT ( QT . getNonReferenceType ( ) ) ;
Expr * val = new ( Context ) OpaqueValueExpr ( SourceLocation ( ) , NonRefQT ,
2012-10-10 22:55:40 +00:00
VK ) ;
2012-09-05 09:37:39 +00:00
GivenArgs . push_back ( val ) ;
}
// Type names should be comma separated.
2013-03-25 16:17:01 +00:00
// FIXME: Here if we have type followed by name won't work. Eg int f, ...
2012-09-05 09:37:39 +00:00
if ( ! P . getCurToken ( ) . is ( clang : : tok : : comma ) ) {
break ;
}
// Eat the comma.
2012-09-18 11:45:00 +00:00
P . ConsumeToken ( ) ;
2012-09-05 09:37:39 +00:00
}
if ( P . getCurToken ( ) . isNot ( tok : : eof ) ) {
// We did not consume all of the prototype, bad parse.
return TheDecl ;
}
//
2012-10-26 13:32:41 +00:00
// Cleanup after prototype parse.
//
P . SkipUntil ( clang : : tok : : eof , /*StopAtSemi*/ false , /*DontConsume*/ false ,
/*StopAtCodeCompletion*/ false ) ;
S . getDiagnostics ( ) . Reset ( ) ;
//
// Setup to reparse as a type.
//
//
2012-09-05 09:37:39 +00:00
// Create a fake file to parse the function name.
//
{
llvm : : MemoryBuffer * SB
= llvm : : MemoryBuffer : : getMemBufferCopy ( funcName . str ( )
+ " \n " , " lookup.funcname.file " ) ;
clang : : FileID FID = S . getSourceManager ( ) . createFileIDForMemBuffer ( SB ) ;
PP . EnterSourceFile ( FID , /*DirLookup=*/ 0 , clang : : SourceLocation ( ) ) ;
PP . Lex ( const_cast < clang : : Token & > ( P . getCurToken ( ) ) ) ;
}
{
//
// Parse the function name.
//
SourceLocation TemplateKWLoc ;
UnqualifiedId FuncId ;
CXXScopeSpec SS ;
SS . MakeTrivial ( Context , classNNS , SourceRange ( ) ) ;
//
// 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.
//
2012-09-18 11:45:00 +00:00
P . EnterScope ( Scope : : DeclScope ) ;
2012-09-05 09:37:39 +00:00
S . EnterDeclaratorContext ( P . getCurScope ( ) , foundDC ) ;
2012-09-18 11:45:00 +00:00
if ( P . ParseUnqualifiedId ( SS , /*EnteringContext*/ false ,
/*AllowDestructorName*/ true ,
/*AllowConstructorName*/ true ,
clang : : ParsedType ( ) , TemplateKWLoc ,
FuncId ) ) {
2012-09-05 09:37:39 +00:00
// Bad parse.
// Destroy the scope we created first, and
// restore the original.
S . ExitDeclaratorContext ( P . getCurScope ( ) ) ;
2012-09-18 11:45:00 +00:00
P . ExitScope ( ) ;
2012-09-05 09:37:39 +00:00
// Then cleanup and exit.
return TheDecl ;
}
//
// Get any template args in the function name.
//
TemplateArgumentListInfo FuncTemplateArgsBuffer ;
DeclarationNameInfo FuncNameInfo ;
const TemplateArgumentListInfo * FuncTemplateArgs ;
S . DecomposeUnqualifiedId ( FuncId , FuncTemplateArgsBuffer , FuncNameInfo ,
FuncTemplateArgs ) ;
//
// Lookup the function name in the given class now.
//
DeclarationName FuncName = FuncNameInfo . getName ( ) ;
SourceLocation FuncNameLoc = FuncNameInfo . getLoc ( ) ;
LookupResult Result ( S , FuncName , FuncNameLoc , Sema : : LookupMemberName ,
Sema : : NotForRedeclaration ) ;
if ( ! S . LookupQualifiedName ( Result , foundDC ) ) {
// Lookup failed.
// Destroy the scope we created first, and
// restore the original.
S . ExitDeclaratorContext ( P . getCurScope ( ) ) ;
2012-09-18 11:45:00 +00:00
P . ExitScope ( ) ;
2012-09-05 09:37:39 +00:00
// Then cleanup and exit.
return TheDecl ;
}
// Destroy the scope we created, and
// restore the original.
S . ExitDeclaratorContext ( P . getCurScope ( ) ) ;
2012-09-18 11:45:00 +00:00
P . ExitScope ( ) ;
2012-09-05 09:37:39 +00:00
//
// Check for lookup failure.
//
if ( ! ( Result . getResultKind ( ) = = LookupResult : : Found ) & &
! ( Result . getResultKind ( ) = = LookupResult : : FoundOverloaded ) ) {
// Lookup failed.
return TheDecl ;
}
2012-10-10 20:14:23 +00:00
{
2012-09-05 09:37:39 +00:00
//
2012-10-10 20:14:23 +00:00
// Construct the overload candidate set.
2012-09-05 09:37:39 +00:00
//
2012-10-10 20:14:23 +00:00
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 ,
2012-09-05 09:37:39 +00:00
llvm : : makeArrayRef < Expr * > ( GivenArgs . data ( ) , GivenArgs . size ( ) ) ,
2012-10-10 20:14:23 +00:00
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 ) ;
}
2012-09-05 09:37:39 +00:00
}
2012-10-10 20:14:23 +00:00
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 ) ;
2012-09-05 09:37:39 +00:00
}
2012-10-10 20:14:23 +00:00
}
}
//
// 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 ;
2012-10-24 20:28:03 +00:00
// We prefer to get the canonical decl for consistency and ease
// of comparison.
TheDecl = TheDecl - > getCanonicalDecl ( ) ;
2012-09-05 09:37:39 +00:00
}
}
}
}
return TheDecl ;
}
const FunctionDecl * LookupHelper : : findFunctionArgs ( const Decl * scopeDecl ,
llvm : : StringRef funcName ,
llvm : : StringRef funcArgs ) const {
//
// Our return value.
//
FunctionDecl * TheDecl = 0 ;
//
// Some utilities.
//
// Use P for shortness
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
Preprocessor & PP = S . getPreprocessor ( ) ;
ASTContext & Context = S . getASTContext ( ) ;
2012-10-12 16:09:04 +00:00
2012-11-20 13:17:55 +00:00
ParserStateRAII ResetParserState ( P ) ;
2012-10-12 16:09:04 +00:00
prepareForParsing ( funcArgs , llvm : : StringRef ( " func.args.file " ) ) ;
2012-09-05 09:37:39 +00:00
//
// Convert the passed decl into a nested name specifier,
// a scope spec, and a decl context.
//
NestedNameSpecifier * classNNS = 0 ;
if ( const NamespaceDecl * NSD = dyn_cast < const NamespaceDecl > ( scopeDecl ) ) {
classNNS = NestedNameSpecifier : : Create ( Context , 0 ,
const_cast < NamespaceDecl * > ( NSD ) ) ;
}
else if ( const RecordDecl * RD = dyn_cast < const 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 ;
}
CXXScopeSpec SS ;
SS . MakeTrivial ( Context , classNNS , SourceRange ( ) ) ;
DeclContext * foundDC = dyn_cast < DeclContext > ( const_cast < Decl * > ( scopeDecl ) ) ;
//
// Some validity checks on the passed decl.
//
if ( foundDC - > isDependentContext ( ) ) {
// Passed decl is a template, we cannot use it.
return 0 ;
}
if ( S . RequireCompleteDeclContext ( SS , foundDC ) ) {
// Forward decl or instantiation failure, we cannot use it.
return 0 ;
}
//
// Get ready for arg list parsing.
//
llvm : : SmallVector < QualType , 4 > GivenArgTypes ;
llvm : : SmallVector < Expr * , 4 > GivenArgs ;
//
// If we are looking up a member function, construct
// the implicit object argument.
//
// Note: For now this is always a non-CV qualified lvalue.
//
QualType ClassType ;
Expr * ObjExpr = 0 ;
2012-10-14 15:30:05 +00:00
Expr : : Classification ObjExprClassification = Expr : : Classification ( ) ;
2012-09-05 09:37:39 +00:00
if ( CXXRecordDecl * CRD = dyn_cast < CXXRecordDecl > ( foundDC ) ) {
ClassType = Context . getTypeDeclType ( CRD ) . getCanonicalType ( ) ;
ObjExpr = new ( Context ) OpaqueValueExpr ( SourceLocation ( ) ,
ClassType , VK_LValue ) ;
ObjExprClassification = ObjExpr - > Classify ( Context ) ;
//GivenArgTypes.insert(GivenArgTypes.begin(), ClassType);
//GivenArgs.insert(GivenArgs.begin(), ObjExpr);
}
2012-10-12 16:09:04 +00:00
2012-09-05 09:37:39 +00:00
//
// Parse the arguments now.
//
{
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 ) ) {
2012-09-18 11:45:00 +00:00
ExprResult Res = P . ParseAssignmentExpression ( ) ;
2012-09-05 09:37:39 +00:00
if ( Res . isUsable ( ) ) {
Expr * expr = Res . release ( ) ;
GivenArgs . push_back ( expr ) ;
QualType QT = expr - > getType ( ) . getCanonicalType ( ) ;
QualType NonRefQT ( QT . getNonReferenceType ( ) ) ;
GivenArgTypes . push_back ( NonRefQT ) ;
if ( first_time ) {
first_time = false ;
}
else {
proto + = ' , ' ;
}
std : : string empty ;
llvm : : raw_string_ostream tmp ( empty ) ;
expr - > printPretty ( tmp , /*PrinterHelper=*/ 0 , Policy ,
/*Indentation=*/ 0 ) ;
proto + = tmp . str ( ) ;
}
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
}
}
}
2013-01-06 05:53:26 +00: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 ) ) {
2012-09-05 09:37:39 +00:00
// We did not consume all of the arg list, bad parse.
return TheDecl ;
}
{
2012-10-26 13:32:41 +00:00
//
// Cleanup after the arg list parse.
//
P . SkipUntil ( clang : : tok : : eof , /*StopAtSemi*/ false , /*DontConsume*/ false ,
/*StopAtCodeCompletion*/ false ) ;
S . getDiagnostics ( ) . Reset ( ) ;
//
// Setup to reparse as a type.
//
//
// Create a fake file to parse the function name.
//
2012-09-05 09:37:39 +00: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 ( ) ) ) ;
}
//
// 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.
//
2012-09-18 11:45:00 +00:00
P . EnterScope ( Scope : : DeclScope ) ;
2012-09-05 09:37:39 +00:00
S . EnterDeclaratorContext ( P . getCurScope ( ) , foundDC ) ;
//
// Parse the function name.
//
SourceLocation TemplateKWLoc ;
UnqualifiedId FuncId ;
2012-09-18 11:45:00 +00:00
if ( P . ParseUnqualifiedId ( SS , /*EnteringContext*/ false ,
/*AllowDestructorName*/ true ,
/*AllowConstructorName*/ true ,
ParsedType ( ) , TemplateKWLoc , FuncId ) ) {
2012-09-05 09:37:39 +00:00
// Failed parse, cleanup.
S . ExitDeclaratorContext ( P . getCurScope ( ) ) ;
2012-09-18 11:45:00 +00:00
P . ExitScope ( ) ;
2012-09-05 09:37:39 +00:00
return TheDecl ;
}
//
// Get any template args in the function name.
//
TemplateArgumentListInfo FuncTemplateArgsBuffer ;
DeclarationNameInfo FuncNameInfo ;
const TemplateArgumentListInfo * FuncTemplateArgs ;
S . DecomposeUnqualifiedId ( FuncId , FuncTemplateArgsBuffer , FuncNameInfo ,
FuncTemplateArgs ) ;
//
// Lookup the function name in the given class now.
//
DeclarationName FuncName = FuncNameInfo . getName ( ) ;
SourceLocation FuncNameLoc = FuncNameInfo . getLoc ( ) ;
LookupResult Result ( S , FuncName , FuncNameLoc , Sema : : LookupMemberName ,
Sema : : NotForRedeclaration ) ;
if ( ! S . LookupQualifiedName ( Result , foundDC ) ) {
// Lookup failed.
// Destroy the scope we created first, and
// restore the original.
S . ExitDeclaratorContext ( P . getCurScope ( ) ) ;
2012-09-18 11:45:00 +00:00
P . ExitScope ( ) ;
2012-09-05 09:37:39 +00:00
// Then cleanup and exit.
return TheDecl ;
}
//
// Destroy the scope we created, and restore the original.
//
S . ExitDeclaratorContext ( P . getCurScope ( ) ) ;
2012-09-18 11:45:00 +00:00
P . ExitScope ( ) ;
2012-09-05 09:37:39 +00:00
//
// Check for lookup failure.
//
if ( ! ( Result . getResultKind ( ) = = LookupResult : : Found ) & &
! ( Result . getResultKind ( ) = = LookupResult : : FoundOverloaded ) ) {
// Lookup failed.
return TheDecl ;
}
{
//
// 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 {
}
}
//
// 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 ;
2012-10-24 20:28:03 +00:00
// We prefer to get the canonical decl for consistency and ease
// of comparison.
TheDecl = TheDecl - > getCanonicalDecl ( ) ;
2012-09-05 09:37:39 +00:00
}
}
}
}
return TheDecl ;
}
void LookupHelper : : findArgList ( llvm : : StringRef argList ,
llvm : : SmallVector < Expr * , 4 > & argExprs ) const {
//
// Some utilities.
//
// Use P for shortness
Parser & P = * m_Parser ;
2012-11-20 13:17:55 +00:00
ParserStateRAII ResetParserState ( P ) ;
2012-10-12 16:09:04 +00:00
prepareForParsing ( argList , llvm : : StringRef ( " arg.list.file " ) ) ;
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 ( ) ) {
argExprs . push_back ( Res . release ( ) ) ;
}
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 ( ) ;
}
}
2012-10-12 15:27:02 +00:00
void LookupHelper : : prepareForParsing ( llvm : : StringRef code ,
llvm : : StringRef bufferName ) const {
Parser & P = * m_Parser ;
Sema & S = P . getActions ( ) ;
Preprocessor & PP = P . getPreprocessor ( ) ;
//
// Tell the diagnostic engine to ignore all diagnostics.
//
PP . getDiagnostics ( ) . setSuppressAllDiagnostics ( true ) ;
//
// Tell the parser to not attempt spelling correction.
//
const_cast < LangOptions & > ( PP . getLangOpts ( ) ) . SpellChecking = 0 ;
//
// Create a fake file to parse the type name.
//
llvm : : MemoryBuffer * SB
= llvm : : MemoryBuffer : : getMemBufferCopy ( code . str ( ) + " \n " ,
bufferName . str ( ) ) ;
FileID FID = S . getSourceManager ( ) . createFileIDForMemBuffer ( SB ) ;
//
// Turn on ignoring of the main file eof token.
//
// Note: We need this because token readahead in the following
// routine calls ends up parsing it multiple times.
//
if ( ! PP . isIncrementalProcessingEnabled ( ) ) {
PP . enableIncrementalProcessing ( ) ;
}
//
// Switch to the new file the way #include does.
//
// Note: To switch back to the main file we must consume an eof token.
//
PP . EnterSourceFile ( FID , /*DirLookup=*/ 0 , SourceLocation ( ) ) ;
PP . Lex ( const_cast < Token & > ( P . getCurToken ( ) ) ) ;
}
2012-09-05 09:37:39 +00:00
} // end namespace cling