Add matchFunctionProto returning the decl only in case of exact match.

The new call is:

const clang::FunctionDecl* matchFunctionProto(const clang::Decl* scopeDecl,
                                              llvm::StringRef funcName,
                                              llvm::StringRef funcProto,
                                              bool objectIsConst
                                              ) const;

and the function must match in name and prototype (including constness).
The only thing not checked is the actual declaration context.
This commit is contained in:
Philippe Canal 2013-08-12 13:30:55 -05:00 committed by sftnight
parent d53e192286
commit 39d8a3e8a6
3 changed files with 154 additions and 3 deletions

View File

@ -96,6 +96,24 @@ namespace cling {
bool objectIsConst = false) const;
///\brief Lookup a function based on its Decl(Context), name and parameters.
/// where the result if any must have exactly the arguments requested.
///
///\param[in] scopeDecl - the scope (namespace or tag) that is searched for
/// the function.
///\param[in] funcName - the name of the function to find.
///\param[in] funcProto - the function parameter list (without enclosing
/// parantheses). Example: "size_t,int".
///\param[in] objectIsConst - if true search fo function that can
/// be called on a const object ; default to false.
///\returns The function found or null.
const clang::FunctionDecl* matchFunctionProto(const clang::Decl* scopeDecl,
llvm::StringRef funcName,
llvm::StringRef funcProto,
bool objectIsConst
) const;
///\brief Lookup given argument list and return each argument as an
/// expression.
///

View File

@ -416,7 +416,8 @@ namespace cling {
static bool IsOverload(const ASTContext& C,
const TemplateArgumentListInfo* FuncTemplateArgs,
const llvm::SmallVector<QualType, 4>& GivenArgTypes,
FunctionDecl* FD, bool UseUsingDeclRules) {
const FunctionDecl* FD) {
//FunctionTemplateDecl* FTD = FD->getDescribedFunctionTemplate();
QualType FQT = C.getCanonicalType(FD->getType());
if (llvm::isa<FunctionNoProtoType>(FQT.getTypePtr())) {
@ -547,6 +548,49 @@ namespace cling {
return TheDecl;
}
static
const FunctionDecl* matchFunctionSelector(DeclContext* foundDC,
bool objectIsConst,
const llvm::SmallVector<Expr*, 4> &GivenArgs,
LookupResult &Result,
DeclarationNameInfo &FuncNameInfo,
const TemplateArgumentListInfo* FuncTemplateArgs,
ASTContext& Context, Parser &P, Sema &S) {
//
// Our return value.
//
const FunctionDecl* TheDecl = overloadFunctionSelector(foundDC, objectIsConst,
GivenArgs, Result,
FuncNameInfo,
FuncTemplateArgs,
Context,P,S);
if (TheDecl) {
llvm::SmallVector<QualType, 4> GivenArgTypes;
for( size_t s = 0 ; s < GivenArgs.size(); ++s) {
GivenArgTypes.push_back( GivenArgs[s]->getType().getCanonicalType() );
}
if ( IsOverload( Context, FuncTemplateArgs, GivenArgTypes, TheDecl) ) {
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;
}
template <typename T>
T findFunction(DeclContext* foundDC, CXXScopeSpec &SS,
llvm::StringRef funcName,
@ -765,6 +809,49 @@ namespace cling {
overloadFunctionSelector);
}
const FunctionDecl* LookupHelper::matchFunctionProto(const Decl* scopeDecl,
llvm::StringRef funcName,
llvm::StringRef funcProto,
bool objectIsConst
) const {
assert(scopeDecl && "Decl cannot be null");
//
// Some utilities.
//
// Use P for shortness
Parser& P = *m_Parser;
Sema& S = P.getActions();
ASTContext& Context = S.getASTContext();
//
// Convert the passed decl into a nested name specifier,
// a scope spec, and a decl context.
//
// Do this 'early' to save on the expansive parser setup,
// in case of failure.
//
CXXScopeSpec SS;
DeclContext* foundDC = getContextAndSpec(SS,scopeDecl,Context,S);
if (!foundDC) return 0;
//
// Parse the prototype now.
//
ParserStateRAII ResetParserState(P);
prepareForParsing(funcProto, llvm::StringRef("func.prototype.file"));
llvm::SmallVector<Expr*, 4> GivenArgs;
if (!ParseProto(GivenArgs,Context,P,S) ) {
return 0;
}
Interpreter::PushTransactionRAII pushedT(m_Interpreter);
return findFunction(foundDC, SS,
funcName, GivenArgs, objectIsConst,
Context, P, S,
matchFunctionSelector);
}
static
bool ParseArgs(llvm::SmallVector<Expr*, 4> &GivenArgs,
ASTContext& Context, Parser &P, Sema &S) {

View File

@ -88,6 +88,8 @@ public:
const long &B_n() const { return m_B_i; }
long &B_n() { return m_B_i; }
const long &B_o() const { return m_B_i; }
long B_p(float) const { return 0; }
int B_p(int) { return 0; }
void* operator new(std::size_t sz) { return ::operator new(sz); }
void* operator new(std::size_t sz, void* arena) { return arena; }
void* operator new[](std::size_t sz) { return ::operator new[](sz); }
@ -906,7 +908,7 @@ func_const_B_n_proto->print(llvm::errs());
//CHECK-NEXT: return this->m_B_i;
//CHECK-NEXT: }
const clang::FunctionDecl* func_const_B_m_proto = lookup.findFunctionArgs(class_A, "B_m", "const int&", true);
const clang::FunctionDecl* func_const_B_m_proto = lookup.findFunctionProto(class_A, "B_m", "const int&", true);
const clang::FunctionDecl* func_const_B_o_proto = lookup.findFunctionProto(class_A, "B_o", "", true);
printf("func_const_B_m_proto: 0x%lx\n", (unsigned long) func_const_B_m_proto);
//CHECK: func_const_B_m_proto: 0x0
@ -915,9 +917,53 @@ printf("func_const_B_o_proto: 0x%lx\n", (unsigned long) func_const_B_o_proto);
//CHECK: func_const_B_o_proto: 0x{{[1-9a-f][0-9a-f]*$}}
func_const_B_o_proto->print(llvm::errs());
//CHECK-NEXT: const long &B_o() const {
//CHECK-NEXT: return this->m_B_i;
//CHECK-NEXT: return this->m_B_i;
//CHECK-NEXT: }
// Test exact matches
const clang::FunctionDecl* func_const_B_p_proto = lookup.findFunctionProto(class_A, "B_p", "double", true);
printf("func_const_B_p_proto 1: 0x%lx\n", (unsigned long) func_const_B_p_proto);
//CHECK: func_const_B_p_proto 1: 0x{{[1-9a-f][0-9a-f]*$}}
func_const_B_p_proto->print(llvm::errs());
//CHECK-NEXT: long B_p(float) const {
//CHECK-NEXT: return 0;
//CHECK-NEXT: }
func_const_B_p_proto = lookup.matchFunctionProto(class_A, "B_p", "double", true);
printf("func_const_B_p_proto 2: 0x%lx\n", (unsigned long) func_const_B_p_proto);
//CHECK: func_const_B_p_proto 2: 0x0
func_const_B_p_proto = lookup.matchFunctionProto(class_A, "B_p", "float", true);
printf("func_const_B_p_proto 3: 0x%lx\n", (unsigned long) func_const_B_p_proto);
//CHECK: func_const_B_p_proto 3: 0x{{[1-9a-f][0-9a-f]*$}}
func_const_B_p_proto->print(llvm::errs());
//CHECK-NEXT: long B_p(float) const {
//CHECK-NEXT: return 0;
//CHECK-NEXT: }
func_const_B_p_proto = lookup.matchFunctionProto(class_A, "B_p", "float", false);
printf("func_const_B_p_proto 4: 0x%lx\n", (unsigned long) func_const_B_p_proto);
//CHECK: func_const_B_p_proto 4: 0x0
func_const_B_p_proto = lookup.matchFunctionProto(class_A, "B_p", "int", false);
printf("func_const_B_p_proto 5: 0x%lx\n", (unsigned long) func_const_B_p_proto);
//CHECK: func_const_B_p_proto 5: 0x{{[1-9a-f][0-9a-f]*$}}
func_const_B_p_proto->print(llvm::errs());
//CHECK-NEXT: int B_p(int) {
//CHECK-NEXT: return 0;
//CHECK-NEXT: }
func_const_B_p_proto = lookup.matchFunctionProto(class_A, "B_p", "int", true);
printf("func_const_B_p_proto 6: 0x%lx\n", (unsigned long) func_const_B_p_proto);
//CHECK: func_const_B_p_proto 6: 0x0
func_const_B_p_proto = lookup.matchFunctionProto(class_A, "B_p", "short", false);
printf("func_const_B_p_proto 6: 0x%lx\n", (unsigned long) func_const_B_p_proto);
//CHECK: func_const_B_p_proto 6: 0x0
func_const_B_p_proto = lookup.matchFunctionProto(class_A, "B_p", "long", false);
printf("func_const_B_p_proto 6: 0x%lx\n", (unsigned long) func_const_B_p_proto);
//CHECK: func_const_B_p_proto 6: 0x0
//
// Test finding constructors.