2010-07-17 02:28:27 +08:00
|
|
|
//===-- ClangASTSource.cpp ---------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2010-10-15 11:36:13 +08:00
|
|
|
#include "lldb/Core/Log.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
#include "lldb/Expression/ClangASTSource.h"
|
|
|
|
#include "lldb/Expression/ClangExpression.h"
|
|
|
|
#include "lldb/Expression/ClangExpressionDeclMap.h"
|
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
|
|
|
ClangASTSource::~ClangASTSource() {}
|
|
|
|
|
|
|
|
void ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer) {
|
|
|
|
// Tell Sema to ask us when looking into the translation unit's decl.
|
|
|
|
Context.getTranslationUnitDecl()->setHasExternalVisibleStorage();
|
|
|
|
Context.getTranslationUnitDecl()->setHasExternalLexicalStorage();
|
|
|
|
}
|
|
|
|
|
|
|
|
// These are only required for AST source that want to lazily load
|
|
|
|
// the declarations (or parts thereof) that they return.
|
|
|
|
Decl *ClangASTSource::GetExternalDecl(uint32_t) { return 0; }
|
|
|
|
Stmt *ClangASTSource::GetExternalDeclStmt(uint64_t) { return 0; }
|
|
|
|
|
|
|
|
// These are also optional, although it might help with ObjC
|
|
|
|
// debugging if we have respectable signatures. But a more
|
|
|
|
// efficient interface (that didn't require scanning all files
|
|
|
|
// for method signatures!) might help.
|
|
|
|
Selector ClangASTSource::GetExternalSelector(uint32_t) { return Selector(); }
|
|
|
|
uint32_t ClangASTSource::GetNumExternalSelectors() { return 0; }
|
|
|
|
|
|
|
|
// The core lookup interface.
|
2010-10-15 11:36:13 +08:00
|
|
|
DeclContext::lookup_result ClangASTSource::FindExternalVisibleDeclsByName
|
|
|
|
(
|
|
|
|
const DeclContext *decl_ctx,
|
|
|
|
DeclarationName decl_name
|
|
|
|
)
|
|
|
|
{
|
|
|
|
switch (decl_name.getNameKind()) {
|
2010-06-09 00:52:24 +08:00
|
|
|
// Normal identifiers.
|
|
|
|
case DeclarationName::Identifier:
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Operator names. Not important for now.
|
|
|
|
case DeclarationName::CXXOperatorName:
|
|
|
|
case DeclarationName::CXXLiteralOperatorName:
|
|
|
|
return DeclContext::lookup_result();
|
|
|
|
|
|
|
|
// Using directives found in this context.
|
|
|
|
// Tell Sema we didn't find any or we'll end up getting asked a *lot*.
|
|
|
|
case DeclarationName::CXXUsingDirective:
|
2010-10-15 11:36:13 +08:00
|
|
|
return SetNoExternalVisibleDeclsForName(decl_ctx, decl_name);
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
// These aren't looked up like this.
|
|
|
|
case DeclarationName::ObjCZeroArgSelector:
|
|
|
|
case DeclarationName::ObjCOneArgSelector:
|
|
|
|
case DeclarationName::ObjCMultiArgSelector:
|
|
|
|
return DeclContext::lookup_result();
|
|
|
|
|
|
|
|
// These aren't possible in the global context.
|
|
|
|
case DeclarationName::CXXConstructorName:
|
|
|
|
case DeclarationName::CXXDestructorName:
|
|
|
|
case DeclarationName::CXXConversionFunctionName:
|
|
|
|
return DeclContext::lookup_result();
|
|
|
|
}
|
2010-10-15 11:36:13 +08:00
|
|
|
|
|
|
|
|
|
|
|
std::string name (decl_name.getAsString());
|
|
|
|
if (0 == name.compare ("__va_list_tag") ||
|
|
|
|
0 == name.compare ("__int128_t") ||
|
|
|
|
0 == name.compare ("__uint128_t") ||
|
|
|
|
0 == name.compare ("SEL") ||
|
|
|
|
0 == name.compare ("id") ||
|
|
|
|
0 == name.compare ("Class") ||
|
|
|
|
0 == name.compare ("nil") ||
|
|
|
|
0 == name.compare ("gp_offset") ||
|
|
|
|
0 == name.compare ("fp_offset") ||
|
|
|
|
0 == name.compare ("overflow_arg_area") ||
|
|
|
|
0 == name.compare ("reg_save_area") ||
|
|
|
|
0 == name.find ("__builtin") )
|
|
|
|
{
|
|
|
|
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
|
|
|
|
if (log)
|
|
|
|
log->Printf("Ignoring built-in in find external declarations for name: '%s'", name.c_str());
|
|
|
|
|
|
|
|
return SetNoExternalVisibleDeclsForName(decl_ctx, decl_name);
|
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
llvm::SmallVector<NamedDecl*, 4> Decls;
|
|
|
|
|
2010-10-15 11:36:13 +08:00
|
|
|
NameSearchContext NSC(*this, Decls, decl_name, decl_ctx);
|
|
|
|
DeclMap.GetDecls(NSC, name.c_str());
|
|
|
|
return SetExternalVisibleDeclsForName(decl_ctx, decl_name, Decls);
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2010-09-23 11:01:22 +08:00
|
|
|
void ClangASTSource::MaterializeVisibleDecls(const DeclContext *DC)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
// This is used to support iterating through an entire lexical context,
|
|
|
|
// which isn't something the debugger should ever need to do.
|
|
|
|
bool ClangASTSource::FindExternalLexicalDecls(const DeclContext *DC, llvm::SmallVectorImpl<Decl*> &Decls) {
|
|
|
|
// true is for error, that's good enough for me
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
clang::ASTContext *NameSearchContext::GetASTContext() {
|
|
|
|
return &ASTSource.Context;
|
|
|
|
}
|
|
|
|
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
clang::NamedDecl *NameSearchContext::AddVarDecl(void *type) {
|
|
|
|
IdentifierInfo *ii = Name.getAsIdentifierInfo();
|
2010-09-15 05:59:34 +08:00
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
clang::NamedDecl *Decl = VarDecl::Create(ASTSource.Context,
|
|
|
|
const_cast<DeclContext*>(DC),
|
|
|
|
SourceLocation(),
|
2010-09-15 05:59:34 +08:00
|
|
|
ii,
|
2010-06-09 00:52:24 +08:00
|
|
|
QualType::getFromOpaquePtr(type),
|
|
|
|
0,
|
2010-09-23 11:01:22 +08:00
|
|
|
SC_Static,
|
|
|
|
SC_Static);
|
2010-06-09 00:52:24 +08:00
|
|
|
Decls.push_back(Decl);
|
|
|
|
|
|
|
|
return Decl;
|
|
|
|
}
|
2010-06-23 07:46:24 +08:00
|
|
|
|
|
|
|
clang::NamedDecl *NameSearchContext::AddFunDecl(void *type) {
|
|
|
|
clang::FunctionDecl *Decl = FunctionDecl::Create(ASTSource.Context,
|
|
|
|
const_cast<DeclContext*>(DC),
|
|
|
|
SourceLocation(),
|
|
|
|
Name.getAsIdentifierInfo(),
|
|
|
|
QualType::getFromOpaquePtr(type),
|
|
|
|
NULL,
|
2010-09-23 11:01:22 +08:00
|
|
|
SC_Static,
|
|
|
|
SC_Static,
|
2010-06-23 07:46:24 +08:00
|
|
|
false,
|
|
|
|
true);
|
|
|
|
|
2010-08-13 07:45:38 +08:00
|
|
|
// We have to do more than just synthesize the FunctionDecl. We have to
|
|
|
|
// synthesize ParmVarDecls for all of the FunctionDecl's arguments. To do
|
|
|
|
// this, we raid the function's FunctionProtoType for types.
|
|
|
|
|
2010-06-23 07:46:24 +08:00
|
|
|
QualType QT = QualType::getFromOpaquePtr(type);
|
|
|
|
clang::Type *T = QT.getTypePtr();
|
2010-06-24 02:58:10 +08:00
|
|
|
const FunctionProtoType *FPT = T->getAs<FunctionProtoType>();
|
2010-06-23 07:46:24 +08:00
|
|
|
|
2010-06-24 02:58:10 +08:00
|
|
|
if (FPT)
|
|
|
|
{
|
2010-06-23 07:46:24 +08:00
|
|
|
unsigned NumArgs = FPT->getNumArgs();
|
|
|
|
unsigned ArgIndex;
|
|
|
|
|
2010-06-24 02:58:10 +08:00
|
|
|
ParmVarDecl **ParmVarDecls = new ParmVarDecl*[NumArgs];
|
2010-06-23 07:46:24 +08:00
|
|
|
|
|
|
|
for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex)
|
|
|
|
{
|
|
|
|
QualType ArgQT = FPT->getArgType(ArgIndex);
|
|
|
|
|
|
|
|
ParmVarDecls[ArgIndex] = ParmVarDecl::Create(ASTSource.Context,
|
|
|
|
const_cast<DeclContext*>(DC),
|
|
|
|
SourceLocation(),
|
|
|
|
NULL,
|
|
|
|
ArgQT,
|
|
|
|
NULL,
|
2010-09-23 11:01:22 +08:00
|
|
|
SC_Static,
|
|
|
|
SC_Static,
|
2010-06-23 07:46:24 +08:00
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
Decl->setParams(ParmVarDecls, NumArgs);
|
2010-06-24 02:58:10 +08:00
|
|
|
|
|
|
|
delete [] ParmVarDecls;
|
2010-06-23 07:46:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Decls.push_back(Decl);
|
|
|
|
|
|
|
|
return Decl;
|
|
|
|
}
|
2010-07-27 08:55:47 +08:00
|
|
|
|
|
|
|
clang::NamedDecl *NameSearchContext::AddGenericFunDecl()
|
|
|
|
{
|
|
|
|
QualType generic_function_type(ASTSource.Context.getFunctionType(ASTSource.Context.getSizeType(), // result
|
|
|
|
NULL, // argument types
|
|
|
|
0, // number of arguments
|
|
|
|
true, // variadic?
|
|
|
|
0, // type qualifiers
|
|
|
|
false, // has exception specification?
|
|
|
|
false, // has any exception specification?
|
|
|
|
0, // number of exceptions
|
|
|
|
NULL, // exceptions
|
|
|
|
FunctionType::ExtInfo())); // defaults for noreturn, regparm, calling convention
|
|
|
|
|
|
|
|
return AddFunDecl(generic_function_type.getAsOpaquePtr());
|
|
|
|
}
|
2010-08-04 09:02:13 +08:00
|
|
|
|
|
|
|
clang::NamedDecl *NameSearchContext::AddTypeDecl(void *type)
|
|
|
|
{
|
|
|
|
QualType QT = QualType::getFromOpaquePtr(type);
|
|
|
|
clang::Type *T = QT.getTypePtr();
|
|
|
|
|
|
|
|
if (TagType *tag_type = dyn_cast<clang::TagType>(T))
|
|
|
|
{
|
|
|
|
TagDecl *tag_decl = tag_type->getDecl();
|
|
|
|
|
|
|
|
Decls.push_back(tag_decl);
|
|
|
|
|
|
|
|
return tag_decl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|