Add support for lookup function from QualType(s).
Add new overload for findFunctionProto and matchFunctionProto which rather than taking the list of argument types as a StringRef, take it as a const llvm::SmallVector<clang::QualType, 4>. This avoids the (permanent) allocations inside clang due to the Parsing of types.
This commit is contained in:
parent
7312683eda
commit
467cb93b3e
@ -95,6 +95,21 @@ namespace cling {
|
||||
llvm::StringRef funcArgs,
|
||||
bool objectIsConst = false) const;
|
||||
|
||||
///\brief Lookup a function based on its Decl(Context), name and parameters.
|
||||
///
|
||||
///\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 list of types of the function parameters
|
||||
///\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* findFunctionProto(const clang::Decl* scopeDecl,
|
||||
llvm::StringRef funcName,
|
||||
const llvm::SmallVector<clang::QualType, 4>& funcProto,
|
||||
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.
|
||||
@ -113,6 +128,21 @@ namespace cling {
|
||||
bool objectIsConst
|
||||
) 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 list of types of the function parameters
|
||||
///\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,
|
||||
const llvm::SmallVector<clang::QualType, 4>& funcProto,
|
||||
bool objectIsConst
|
||||
) const;
|
||||
|
||||
///\brief Lookup given argument list and return each argument as an
|
||||
/// expression.
|
||||
|
@ -825,7 +825,37 @@ namespace cling {
|
||||
}
|
||||
|
||||
static
|
||||
bool ParseProto(llvm::SmallVector<Expr*, 4> &GivenArgs,
|
||||
bool getExprProto(llvm::SmallVector<ExprAlloc, 4> &ExprMemory,
|
||||
llvm::SmallVector<Expr*, 4> &GivenArgs,
|
||||
const llvm::SmallVector<QualType, 4> &GivenTypes) {
|
||||
//
|
||||
// Create the array of Expr from the array of Types.
|
||||
//
|
||||
|
||||
typedef llvm::SmallVector<QualType, 4>::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);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
bool ParseProto(llvm::SmallVector<ExprAlloc, 4> &ExprMemory,
|
||||
llvm::SmallVector<Expr*, 4> &GivenArgs,
|
||||
ASTContext& Context, Parser &P,Sema &S) {
|
||||
//
|
||||
// Parse the prototype now.
|
||||
@ -875,6 +905,51 @@ namespace cling {
|
||||
return true;
|
||||
}
|
||||
|
||||
const FunctionDecl* LookupHelper::findFunctionProto(const Decl* scopeDecl,
|
||||
llvm::StringRef funcName,
|
||||
const llvm::SmallVector<QualType, 4>& 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;
|
||||
|
||||
llvm::SmallVector<ExprAlloc, 4> ExprMemory;
|
||||
llvm::SmallVector<Expr*, 4> GivenArgs;
|
||||
if (!funcProto.empty()) {
|
||||
if (!getExprProto(ExprMemory, GivenArgs, funcProto) ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Parse the prototype now.
|
||||
//
|
||||
ParserStateRAII ResetParserState(P);
|
||||
prepareForParsing("", llvm::StringRef("func.prototype.file"));
|
||||
Interpreter::PushTransactionRAII pushedT(m_Interpreter);
|
||||
return findFunction(foundDC, SS,
|
||||
funcName, GivenArgs, objectIsConst,
|
||||
Context, P, S,
|
||||
overloadFunctionSelector);
|
||||
}
|
||||
|
||||
const FunctionDecl* LookupHelper::findFunctionProto(const Decl* scopeDecl,
|
||||
llvm::StringRef funcName,
|
||||
llvm::StringRef funcProto,
|
||||
@ -909,7 +984,7 @@ namespace cling {
|
||||
llvm::SmallVector<ExprAlloc, 4> ExprMemory;
|
||||
llvm::SmallVector<Expr*, 4> GivenArgs;
|
||||
if (!funcProto.empty()) {
|
||||
if (!ParseProto(ExprMemory,GivenArgs,Context,P,S) ) {
|
||||
if (!ParseProto(ExprMemory, GivenArgs,Context,P,S) ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -955,7 +1030,7 @@ namespace cling {
|
||||
llvm::SmallVector<ExprAlloc, 4> ExprMemory;
|
||||
llvm::SmallVector<Expr*, 4> GivenArgs;
|
||||
if (!funcProto.empty()) {
|
||||
if (!ParseProto(ExprMemory, GivenArgs,Context,P,S) ) {
|
||||
if (!ParseProto(ExprMemory,GivenArgs,Context,P,S) ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -967,6 +1042,52 @@ namespace cling {
|
||||
matchFunctionSelector);
|
||||
}
|
||||
|
||||
const FunctionDecl* LookupHelper::matchFunctionProto(const Decl* scopeDecl,
|
||||
llvm::StringRef funcName,
|
||||
const llvm::SmallVector<QualType, 4>& 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;
|
||||
|
||||
|
||||
llvm::SmallVector<ExprAlloc, 4> ExprMemory;
|
||||
llvm::SmallVector<Expr*, 4> GivenArgs;
|
||||
if (!funcProto.empty()) {
|
||||
if (!getExprProto(ExprMemory, GivenArgs, funcProto) ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Parse the prototype now.
|
||||
//
|
||||
ParserStateRAII ResetParserState(P);
|
||||
prepareForParsing("", llvm::StringRef("func.prototype.file"));
|
||||
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) {
|
||||
|
@ -766,6 +766,34 @@ func_B_h_proto->print(llvm::errs());
|
||||
//CHECK-NEXT: }
|
||||
|
||||
|
||||
//
|
||||
// Test finding a member function taking an int and a double argument
|
||||
// in a base class using the preparse types.
|
||||
//
|
||||
llvm::SmallVector<clang::QualType, 4> types;
|
||||
types.push_back(lookup.findType("int"));
|
||||
types.push_back(lookup.findType("float"));
|
||||
const clang::FunctionDecl* func_B_h_proto_type = lookup.findFunctionProto(class_A, "B_h", types);
|
||||
types.pop_back();
|
||||
types.push_back(lookup.findType("double"));
|
||||
const clang::FunctionDecl* func_B_h_match_proto_type = lookup.matchFunctionProto(class_A, "B_h", types, false);
|
||||
|
||||
printf("func_B_h_proto_type: 0x%lx\n", (unsigned long) func_B_h_proto_type);
|
||||
//CHECK: func_B_h_proto_type: 0x{{[1-9a-f][0-9a-f]*$}}
|
||||
func_B_h_proto_type->print(llvm::errs());
|
||||
//CHECK-NEXT: void B_h(int vi, double vd) {
|
||||
//CHECK-NEXT: int x = vi;
|
||||
//CHECK-NEXT: double y = vd;
|
||||
//CHECK-NEXT: }
|
||||
|
||||
printf("func_B_h_match_proto_type: 0x%lx\n", (unsigned long) func_B_h_match_proto_type);
|
||||
//CHECK: func_B_h_match_proto_type: 0x{{[1-9a-f][0-9a-f]*$}}
|
||||
func_B_h_match_proto_type->print(llvm::errs());
|
||||
//CHECK-NEXT: void B_h(int vi, double vd) {
|
||||
//CHECK-NEXT: int x = vi;
|
||||
//CHECK-NEXT: double y = vd;
|
||||
//CHECK-NEXT: }
|
||||
|
||||
|
||||
//
|
||||
// Test finding an overloaded member function in a base class.
|
||||
|
Loading…
Reference in New Issue
Block a user