245 changes: 245 additions & 0 deletions tools/libclang/CIndexCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "CIndexer.h"
#include "CXCursor.h"
#include "CXType.h"
#include "CXString.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"

Expand Down Expand Up @@ -124,5 +125,249 @@ CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {

return MakeCXCursor(Template, static_cast<CXTranslationUnit>(C.data[2]));
}

// =========================================================================================================================================

unsigned clang_getTemplateSpecializationNumArguments(CXCursor C)
{
if (!clang_isDeclaration(C.kind))
return UINT_MAX;

Decl *D = getCursorDecl(C);
if (!D)
return UINT_MAX;

const TemplateArgumentList* TemplateArgList = 0;

if (ClassTemplateSpecializationDecl *ClassSpec
= dyn_cast<ClassTemplateSpecializationDecl>(D)) {

TemplateArgList = &(ClassSpec->getTemplateArgs());

} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
FunctionDecl::TemplatedKind TemplKind = Function->getTemplatedKind();
switch(TemplKind){
case FunctionDecl::TK_MemberSpecialization:
case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
case FunctionDecl::TK_FunctionTemplateSpecialization:
TemplateArgList = Function->getTemplateSpecializationArgs();
break;
default: break;
}
}

return (TemplateArgList == 0) ? UINT_MAX : TemplateArgList->size();
}

CXCursor clang_getTemplateSpecializationArgument(CXCursor C, unsigned Index)
{
if (!clang_isDeclaration(C.kind))
return clang_getNullCursor();

Decl *D = getCursorDecl(C);
if (!D)
return clang_getNullCursor();

const TemplateArgumentList* TemplateArgList = 0;
if (ClassTemplateSpecializationDecl *ClassSpec
= dyn_cast<ClassTemplateSpecializationDecl>(D)) {

TemplateArgList = &(ClassSpec->getTemplateArgs());

} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {

FunctionDecl::TemplatedKind TemplKind = Function->getTemplatedKind();
switch(TemplKind){
case FunctionDecl::TK_MemberSpecialization:
case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
case FunctionDecl::TK_FunctionTemplateSpecialization:
TemplateArgList = Function->getTemplateSpecializationArgs();
break;
default: break;
}

}

if(!TemplateArgList)
return clang_getNullCursor();

assert(Index < TemplateArgList->size() && "getTemplateSpecializationArgument(): Index out of bounds");

return MakeCursorTemplateArgument(&((*TemplateArgList)[Index]), D, static_cast<CXTranslationUnit>(C.data[2]));
}

unsigned clang_isTemplateArgument(CXCursor C)
{
return (C.kind >= CXCursor_TemplateNullArgument && C.kind <= CXCursor_TemplatePackArgument) ? 1 : 0;
}

const TemplateArgument* getTemplateArgumentFromCursor(CXCursor C)
{
if(clang_isTemplateArgument(C) == 0)
return 0;

return static_cast<const TemplateArgument*>(C.data[1]);
}

CXType clang_getTemplateArgumentValueAsType(CXCursor C)
{
CXTranslationUnit TU = cxcursor::getCursorTU(C);
const TemplateArgument* TemplateArg = getTemplateArgumentFromCursor(C);

if(!TemplateArg || TemplateArg->getKind() != TemplateArgument::Type)
return cxtype::MakeCXType(QualType(), TU);

return cxtype::MakeCXType(TemplateArg->getAsType(), TU);
}

long long clang_getTemplateArgumentValueAsIntegral(CXCursor C)
{
const TemplateArgument* TemplateArg = getTemplateArgumentFromCursor(C);

if(!TemplateArg || TemplateArg->getKind() != TemplateArgument::Integral)
return LLONG_MIN;

return TemplateArg->getAsIntegral().getSExtValue();
}

CXCursor clang_getTemplateArgumentValueAsDeclaration(CXCursor C)
{
const TemplateArgument* TemplateArg = getTemplateArgumentFromCursor(C);

if(!TemplateArg || TemplateArg->getKind() != TemplateArgument::Declaration)
return clang_getNullCursor();

Decl* D = TemplateArg->getAsDecl();
if(!D)
return clang_getNullCursor();

CXTranslationUnit TU = cxcursor::getCursorTU(C);

return MakeCXCursor(D, TU);
}

CXCursor clang_getTemplateArgumentValueAsTemplate(CXCursor C)
{
const TemplateArgument* TemplateArg = getTemplateArgumentFromCursor(C);

if(!TemplateArg || TemplateArg->getKind() != TemplateArgument::Template)
return clang_getNullCursor();

TemplateDecl* D = TemplateArg->getAsTemplate().getAsTemplateDecl();
if(!D)
return clang_getNullCursor();

CXTranslationUnit TU = cxcursor::getCursorTU(C);

return MakeCXCursor(D, TU);
}

CXCursor clang_getTemplateArgumentValueAsExpression(CXCursor C)
{
const TemplateArgument* TemplateArg = getTemplateArgumentFromCursor(C);

if(!TemplateArg || TemplateArg->getKind() != TemplateArgument::Expression)
return clang_getNullCursor();

Expr* E = TemplateArg->getAsExpr();
if(!E)
return clang_getNullCursor();

CXTranslationUnit TU = cxcursor::getCursorTU(C);

// FIXME: Currently passes 0 as the parent - how do we get the real parent?
return MakeCXCursor(E, 0, TU);
}

// =========================================================================================================================================

unsigned clang_getTemplateNumParameters(CXCursor C)
{
if (!clang_isDeclaration(C.kind))
return UINT_MAX;

Decl *D = getCursorDecl(C);
if (!D)
return UINT_MAX;

TemplateParameterList* TemplateParamList = 0;
if (RedeclarableTemplateDecl *TempDecl
= dyn_cast<RedeclarableTemplateDecl>(D)) {

TemplateParamList = TempDecl->getTemplateParameters();

} else if (ClassTemplatePartialSpecializationDecl *ClassPartialSpec
= dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {

TemplateParamList = ClassPartialSpec->getTemplateParameters();
}

return (TemplateParamList == 0) ? UINT_MAX : TemplateParamList->size();
}

CXCursor clang_getTemplateParameter(CXCursor C, unsigned Index)
{
if (!clang_isDeclaration(C.kind))
return clang_getNullCursor();

Decl *D = getCursorDecl(C);
if (!D)
return clang_getNullCursor();

TemplateParameterList* TemplateParamList = 0;
if (RedeclarableTemplateDecl *TempDecl
= dyn_cast<RedeclarableTemplateDecl>(D)) {

TemplateParamList = TempDecl->getTemplateParameters();

} else if (ClassTemplatePartialSpecializationDecl *ClassPartialSpec
= dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {

TemplateParamList = ClassPartialSpec->getTemplateParameters();
}

if(!TemplateParamList)
return clang_getNullCursor();

assert(Index < TemplateParamList->size() && "getTemplateParameter(): Index out of bounds");

CXTranslationUnit TU = cxcursor::getCursorTU(C);
return MakeCXCursor(TemplateParamList->getParam(Index), TU);
}

// =========================================================================================================================================


enum CX_CXXAccessSpecifier clang_getCXXMemberAccessSpecifier(CXCursor C)
{
AccessSpecifier spec = AS_none;

switch(C.kind)
{
case CXCursor_CXXMethod:
case CXCursor_ClassDecl:
case CXCursor_StructDecl:
case CXCursor_FieldDecl:
case CXCursor_VarDecl:
case CXCursor_EnumDecl:
case CXCursor_EnumConstantDecl:
case CXCursor_ClassTemplate:
case CXCursor_FunctionTemplate:
case CXCursor_ClassTemplatePartialSpecialization:
spec = getCursorDecl(C)->getAccess();
break;
default:
spec = AS_none;
}

switch (spec) {
case AS_public: return CX_CXXPublic;
case AS_protected: return CX_CXXProtected;
case AS_private: return CX_CXXPrivate;
case AS_none: return CX_CXXInvalidAccessSpecifier;
}

llvm_unreachable("Invalid AccessSpecifier!");
};

} // end extern "C"
23 changes: 23 additions & 0 deletions tools/libclang/CXCursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,29 @@ cxcursor::getCursorOverloadedDeclRef(CXCursor C) {
reinterpret_cast<uintptr_t>(C.data[1])));
}

CXCursor cxcursor::MakeCursorTemplateArgument(const TemplateArgument *Arg, Decl* ParentDecl,
CXTranslationUnit TU) {
assert(Arg && ParentDecl && TU && "Invalid arguments!");

CXCursorKind K;
#define TAKIND(X) case TemplateArgument::X: K = CXCursor_Template##X##Argument; break
switch(Arg->getKind())
{
TAKIND(Null);
TAKIND(Type);
TAKIND(Declaration);
TAKIND(Integral);
TAKIND(Template);
TAKIND(TemplateExpansion);
TAKIND(Expression);
TAKIND(Pack);
}
#undef TAKIND

CXCursor C = { K, 0, { (void*)ParentDecl, (void*)Arg, TU } };
return C;
}

Decl *cxcursor::getCursorDecl(CXCursor Cursor) {
return (Decl *)Cursor.data[0];
}
Expand Down
3 changes: 3 additions & 0 deletions tools/libclang/CXCursor.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class TemplateDecl;
class TemplateName;
class TypeDecl;
class VarDecl;
class TemplateArgument;

namespace cxcursor {

Expand Down Expand Up @@ -194,6 +195,8 @@ typedef llvm::PointerUnion3<OverloadExpr *, Decl *,
/// declaration, or template name along with the source location.
std::pair<OverloadedDeclRefStorage, SourceLocation>
getCursorOverloadedDeclRef(CXCursor C);

CXCursor MakeCursorTemplateArgument(const TemplateArgument* arg, Decl* ParentDecl, CXTranslationUnit TU);

Decl *getCursorDecl(CXCursor Cursor);
Expr *getCursorExpr(CXCursor Cursor);
Expand Down
11 changes: 10 additions & 1 deletion tools/libclang/CXType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ static CXTypeKind GetTypeKind(QualType T) {
TKCASE(FunctionProto);
TKCASE(ConstantArray);
TKCASE(Vector);
TKCASE(TemplateTypeParm);
TKCASE(TemplateSpecialization);
TKCASE(Elaborated);
default:
return CXType_Unexposed;
}
Expand Down Expand Up @@ -361,7 +364,10 @@ CXCursor clang_getTypeDeclaration(CXType CT) {
D = cast<InjectedClassNameType>(TP)->getDecl();
break;

// FIXME: Template type parameters!
// FIXME: Template type parameters!
case Type::TemplateTypeParm:
D = cast<TemplateTypeParmType>(TP)->getDecl();
break;

case Type::Elaborated:
TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
Expand Down Expand Up @@ -425,6 +431,9 @@ CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
TKIND(FunctionProto);
TKIND(ConstantArray);
TKIND(Vector);
TKIND(TemplateTypeParm);
TKIND(TemplateSpecialization);
TKIND(Elaborated);
}
#undef TKIND
return cxstring::createCXString(s);
Expand Down