Implement hasFunction().

Rephrase !(a==b).

This file still needs major refactoring to remove code duplication.


git-svn-id: http://root.cern.ch/svn/root/trunk@49099 27541ba8-7e3a-0410-8455-c3a389f83636
This commit is contained in:
Axel Naumann 2013-04-05 13:50:01 +00:00
parent 89d418feb6
commit 8c680be610
2 changed files with 152 additions and 4 deletions

View File

@ -91,6 +91,11 @@ namespace cling {
void findArgList(llvm::StringRef argList,
llvm::SmallVector<clang::Expr*, 4>& argExprs) const;
///\brief Test whether a function with the given name exists.
bool hasFunction(const clang::Decl* scopeDecl,
llvm::StringRef funcName) const;
private:
void prepareForParsing(llvm::StringRef code,
llvm::StringRef bufferName) const;

View File

@ -529,8 +529,8 @@ namespace cling {
//
// Check for lookup failure.
//
if (!(Result.getResultKind() == LookupResult::Found) &&
!(Result.getResultKind() == LookupResult::FoundOverloaded)) {
if (Result.getResultKind() != LookupResult::Found &&
Result.getResultKind() != LookupResult::FoundOverloaded) {
// Lookup failed.
return TheDecl;
}
@ -814,8 +814,8 @@ namespace cling {
//
// Check for lookup failure.
//
if (!(Result.getResultKind() == LookupResult::Found) &&
!(Result.getResultKind() == LookupResult::FoundOverloaded)) {
if (Result.getResultKind() != LookupResult::Found &&
Result.getResultKind() != LookupResult::FoundOverloaded) {
// Lookup failed.
return TheDecl;
}
@ -978,4 +978,147 @@ namespace cling {
}
bool LookupHelper::hasFunction(const clang::Decl* scopeDecl,
llvm::StringRef funcName) const {
//FIXME: remore code duplication with findFunctionArgs() and friends.
assert(scopeDecl && "Decl cannot be null");
//
// Our return value.
//
FunctionDecl* TheDecl = 0;
//
// Some utilities.
//
Parser& P = *m_Parser;
Sema& S = P.getActions();
Preprocessor& PP = S.getPreprocessor();
ASTContext& Context = S.getASTContext();
ParserStateRAII ResetParserState(P);
//
// 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));
//
// 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);
}
//
// Setup to reparse as a type.
//
//
// Create a fake file to parse the function name.
//
{
llvm::MemoryBuffer* SB
= llvm::MemoryBuffer::getMemBufferCopy(funcName.str()
+ "\n", "lookup.funcname.file");
clang::FileID FID = S.getSourceManager().createFileIDForMemBuffer(SB);
PP.EnterSourceFile(FID, /*DirLookup=*/0, clang::SourceLocation());
PP.Lex(const_cast<clang::Token&>(P.getCurToken()));
}
{
//
// 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.
//
P.EnterScope(Scope::DeclScope);
S.EnterDeclaratorContext(P.getCurScope(), foundDC);
if (P.ParseUnqualifiedId(SS, /*EnteringContext*/false,
/*AllowDestructorName*/true,
/*AllowConstructorName*/true,
clang::ParsedType(), TemplateKWLoc,
FuncId)) {
// Bad parse.
// Destroy the scope we created first, and
// restore the original.
S.ExitDeclaratorContext(P.getCurScope());
P.ExitScope();
// 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());
P.ExitScope();
// Then cleanup and exit.
return TheDecl;
}
// Destroy the scope we created, and
// restore the original.
S.ExitDeclaratorContext(P.getCurScope());
P.ExitScope();
//
// 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;
}
return false;
}
} // end namespace cling