Add support for restricting the function search to const functions.

Add an optional argument objectIsConst to findFunctionArgs and
findFunctionProto:

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

   const clang::FunctionDecl* findFunctionArgs(const clang::Decl* scopeDecl,
                                               llvm::StringRef funcName,
                                               llvm::StringRef funcArgs,
                                               bool objectIsConst) const;
This commit is contained in:
Philippe Canal 2013-08-06 11:06:44 -05:00 committed by sftnight
parent bc5c795693
commit 31b60e0ab5
3 changed files with 84 additions and 18 deletions

View File

@ -81,14 +81,20 @@ namespace cling {
///\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,optional] 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* findFunctionProto(const clang::Decl* scopeDecl,
llvm::StringRef funcName,
llvm::StringRef funcProto) const;
llvm::StringRef funcProto,
bool objectIsConst = false
) const;
const clang::FunctionDecl* findFunctionArgs(const clang::Decl* scopeDecl,
llvm::StringRef funcName,
llvm::StringRef funcArgs) const;
llvm::StringRef funcArgs,
bool objectIsConst = false) const;
///\brief Lookup given argument list and return each argument as an
/// expression.

View File

@ -400,6 +400,7 @@ namespace cling {
static
const FunctionDecl* overloadFunctionSelector(DeclContext* foundDC,
bool objectIsConst,
const llvm::SmallVector<Expr*, 4> &GivenArgs,
LookupResult &Result,
DeclarationNameInfo &FuncNameInfo,
@ -420,7 +421,9 @@ namespace cling {
Expr* ObjExpr = 0;
Expr::Classification ObjExprClassification;
if (CXXRecordDecl* CRD = dyn_cast<CXXRecordDecl>(foundDC)) {
ClassType = Context.getTypeDeclType(CRD).getCanonicalType();
if (objectIsConst)
ClassType = Context.getTypeDeclType(CRD).getCanonicalType().withConst();
else ClassType = Context.getTypeDeclType(CRD).getCanonicalType();
OpaqueValueExpr ObjExpr(SourceLocation(),
ClassType, VK_LValue);
ObjExprClassification = ObjExpr.Classify(Context);
@ -514,8 +517,10 @@ namespace cling {
T findFunction(DeclContext* foundDC, CXXScopeSpec &SS,
llvm::StringRef funcName,
const llvm::SmallVector<Expr*, 4> &GivenArgs,
bool objectIsConst,
ASTContext& Context, Parser &P, Sema &S,
T (*functionSelector)(DeclContext* foundDC,
bool objectIsConst,
const llvm::SmallVector<Expr*, 4> &GivenArgs,
LookupResult &Result,
DeclarationNameInfo &FuncNameInfo,
@ -625,7 +630,7 @@ namespace cling {
// Lookup failed.
return TheDecl;
}
return functionSelector(foundDC,GivenArgs,
return functionSelector(foundDC,objectIsConst,GivenArgs,
Result,
FuncNameInfo,
FuncTemplateArgs,
@ -633,8 +638,8 @@ namespace cling {
}
static
bool findFunctionParseProto(llvm::SmallVector<Expr*, 4> &GivenArgs,
ASTContext& Context, Parser &P,Sema &S) {
bool ParseProto(llvm::SmallVector<Expr*, 4> &GivenArgs,
ASTContext& Context, Parser &P,Sema &S) {
//
// Parse the prototype now.
//
@ -686,7 +691,9 @@ namespace cling {
const FunctionDecl* LookupHelper::findFunctionProto(const Decl* scopeDecl,
llvm::StringRef funcName,
llvm::StringRef funcProto) const {
llvm::StringRef funcProto,
bool objectIsConst
) const {
assert(scopeDecl && "Decl cannot be null");
//
// Some utilities.
@ -714,19 +721,19 @@ namespace cling {
prepareForParsing(funcProto, llvm::StringRef("func.prototype.file"));
llvm::SmallVector<Expr*, 4> GivenArgs;
if (!findFunctionParseProto(GivenArgs,Context,P,S) ) {
if (!ParseProto(GivenArgs,Context,P,S) ) {
return 0;
}
return findFunction(foundDC, SS,
funcName, GivenArgs,
funcName, GivenArgs, objectIsConst,
Context, P, S,
overloadFunctionSelector);
}
static
bool findFunctionParseArgs(llvm::SmallVector<Expr*, 4> &GivenArgs,
ASTContext& Context, Parser &P, Sema &S) {
bool ParseArgs(llvm::SmallVector<Expr*, 4> &GivenArgs,
ASTContext& Context, Parser &P, Sema &S) {
//
// Parse the arguments now.
@ -784,8 +791,10 @@ namespace cling {
}
const FunctionDecl* LookupHelper::findFunctionArgs(const Decl* scopeDecl,
llvm::StringRef funcName,
llvm::StringRef funcArgs) const {
llvm::StringRef funcName,
llvm::StringRef funcArgs,
bool objectIsConst
) const {
assert(scopeDecl && "Decl cannot be null");
//
// Some utilities.
@ -813,12 +822,12 @@ namespace cling {
prepareForParsing(funcArgs, llvm::StringRef("func.args.file"));
llvm::SmallVector<Expr*, 4> GivenArgs;
if (!findFunctionParseArgs(GivenArgs,Context,P,S) ) {
if (!ParseArgs(GivenArgs,Context,P,S) ) {
return 0;
}
return findFunction(foundDC, SS,
funcName, GivenArgs,
funcName, GivenArgs, objectIsConst,
Context, P, S, overloadFunctionSelector);
}
@ -897,6 +906,7 @@ namespace cling {
static
bool hasFunctionSelector(DeclContext* ,
bool /* objectIsConst */,
const llvm::SmallVector<Expr*, 4> &,
LookupResult &Result,
DeclarationNameInfo &,
@ -945,7 +955,7 @@ namespace cling {
llvm::SmallVector<Expr*, 4> GivenArgs;
return findFunction(foundDC, SS,
funcName, GivenArgs,
funcName, GivenArgs, false /* objectIsConst */,
Context, P, S, hasFunctionSelector);
}

View File

@ -85,6 +85,9 @@ public:
void B_j(int vi, double vd) { int x = vi; double y = vd; }
template <class T> void B_k(T v) { T x = v; }
void B_m(const int& v) { int y = v; }
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; }
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); }
@ -844,8 +847,6 @@ func_B_k2_proto->print(llvm::errs());
//CHECK-NEXT: double x = v;
//CHECK-NEXT: }
//
// Test finding a member function taking a const int reference arg in a base class.
//
@ -868,6 +869,55 @@ func_B_m_proto->print(llvm::errs());
//CHECK-NEXT: }
//
// Test finding a member function that const or not
//
const clang::FunctionDecl* func_B_n_args = lookup.findFunctionArgs(class_A, "B_n", "", false);
const clang::FunctionDecl* func_B_n_proto = lookup.findFunctionProto(class_A, "B_n", "", false);
printf("func_B_n_args: 0x%lx\n", (unsigned long) func_B_n_args);
//CHECK: func_B_n_args: 0x{{[1-9a-f][0-9a-f]*$}}
func_B_n_args->print(llvm::errs());
//CHECK-NEXT: long &B_n() {
//CHECK-NEXT: return this->m_B_i;
//CHECK-NEXT: }
printf("func_B_n_proto: 0x%lx\n", (unsigned long) func_B_n_proto);
//CHECK: func_B_n_proto: 0x{{[1-9a-f][0-9a-f]*$}}
func_B_n_proto->print(llvm::errs());
//CHECK-NEXT: long &B_n() {
//CHECK-NEXT: return this->m_B_i;
//CHECK-NEXT: }
const clang::FunctionDecl* func_const_B_n_args = lookup.findFunctionArgs(class_A, "B_n", "", true);
const clang::FunctionDecl* func_const_B_n_proto = lookup.findFunctionProto(class_A, "B_n", "", true);
printf("func_const_B_n_args: 0x%lx\n", (unsigned long) func_const_B_n_args);
//CHECK: func_const_B_n_args: 0x{{[1-9a-f][0-9a-f]*$}}
func_const_B_n_args->print(llvm::errs());
//CHECK-NEXT: const long &B_n() const {
//CHECK-NEXT: return this->m_B_i;
//CHECK-NEXT: }
printf("func_const_B_n_proto: 0x%lx\n", (unsigned long) func_const_B_n_proto);
//CHECK: func_const_B_n_proto: 0x{{[1-9a-f][0-9a-f]*$}}
func_const_B_n_proto->print(llvm::errs());
//CHECK-NEXT: const long &B_n() const {
//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_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
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: }
//
// Test finding constructors.