forked from OSchip/llvm-project
Implement CXCursor support for walking C++ base specifiers. This includes adding the API hooks clang_isVirtualBase() and clang_getCXXAccessSpecifier() to query properties of the base specifier.
Implements <rdar://problem/8274883>. llvm-svn: 112296
This commit is contained in:
parent
2c2c5f3789
commit
ae9e221513
|
@ -1001,7 +1001,8 @@ enum CXCursorKind {
|
||||||
* referenced by the type of size is the typedef for size_type.
|
* referenced by the type of size is the typedef for size_type.
|
||||||
*/
|
*/
|
||||||
CXCursor_TypeRef = 43,
|
CXCursor_TypeRef = 43,
|
||||||
CXCursor_LastRef = 43,
|
CXCursor_CXXBaseSpecifier = 44,
|
||||||
|
CXCursor_LastRef = CXCursor_CXXBaseSpecifier,
|
||||||
|
|
||||||
/* Error conditions */
|
/* Error conditions */
|
||||||
CXCursor_FirstInvalid = 70,
|
CXCursor_FirstInvalid = 70,
|
||||||
|
@ -1438,6 +1439,29 @@ CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C);
|
||||||
*/
|
*/
|
||||||
CINDEX_LINKAGE unsigned clang_isPODType(CXType T);
|
CINDEX_LINKAGE unsigned clang_isPODType(CXType T);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Returns 1 if the base class specified by the cursor with kind
|
||||||
|
* CX_CXXBaseSpecifier is virtual.
|
||||||
|
*/
|
||||||
|
CINDEX_LINKAGE unsigned clang_isVirtualBase(CXCursor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Represents the C++ access control level to a base class for a
|
||||||
|
* cursor with kind CX_CXXBaseSpecifier.
|
||||||
|
*/
|
||||||
|
enum CX_CXXAccessSpecifier {
|
||||||
|
CX_CXXInvalidAccessSpecifier,
|
||||||
|
CX_CXXPublic,
|
||||||
|
CX_CXXProtected,
|
||||||
|
CX_CXXPrivate
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Returns the access control level for the C++ base specifier
|
||||||
|
* represented by a cursor with kind CX_CXXBaseSpecifier.
|
||||||
|
*/
|
||||||
|
CINDEX_LINKAGE enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -10,6 +10,21 @@ void f(int x) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test handling of C++ base specifiers.
|
||||||
|
class A {
|
||||||
|
void doA();
|
||||||
|
};
|
||||||
|
|
||||||
|
class B {
|
||||||
|
void doB();
|
||||||
|
};
|
||||||
|
|
||||||
|
class C : public A, private B {
|
||||||
|
void doC();
|
||||||
|
};
|
||||||
|
|
||||||
|
class D : virtual public C, virtual private A {};
|
||||||
|
|
||||||
// RUN: c-index-test -test-load-source all %s | FileCheck %s
|
// RUN: c-index-test -test-load-source all %s | FileCheck %s
|
||||||
// CHECK: load-stmts.cpp:1:13: TypedefDecl=T:1:13 (Definition) Extent=[1:13 - 1:14]
|
// CHECK: load-stmts.cpp:1:13: TypedefDecl=T:1:13 (Definition) Extent=[1:13 - 1:14]
|
||||||
// CHECK: load-stmts.cpp:2:8: StructDecl=X:2:8 (Definition) Extent=[2:1 - 2:23]
|
// CHECK: load-stmts.cpp:2:8: StructDecl=X:2:8 (Definition) Extent=[2:1 - 2:23]
|
||||||
|
@ -56,4 +71,15 @@ void f(int x) {
|
||||||
// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[9:3 - 9:17]
|
// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[9:3 - 9:17]
|
||||||
// CHECK: load-stmts.cpp:9:8: UnexposedExpr= Extent=[9:8 - 9:10]
|
// CHECK: load-stmts.cpp:9:8: UnexposedExpr= Extent=[9:8 - 9:10]
|
||||||
// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[9:12 - 9:17]
|
// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[9:12 - 9:17]
|
||||||
|
// CHECK: load-stmts.cpp:14:7: ClassDecl=A:14:7 (Definition) Extent=[14:1 - 16:2]
|
||||||
|
// CHECK: load-stmts.cpp:15:8: CXXMethod=doA:15:8 Extent=[15:8 - 15:13]
|
||||||
|
// CHECK: load-stmts.cpp:18:7: ClassDecl=B:18:7 (Definition) Extent=[18:1 - 20:2]
|
||||||
|
// CHECK: load-stmts.cpp:19:8: CXXMethod=doB:19:8 Extent=[19:8 - 19:13]
|
||||||
|
// CHECK: load-stmts.cpp:22:7: ClassDecl=C:22:7 (Definition) Extent=[22:1 - 24:2]
|
||||||
|
// CHECK: <invalid loc>:0:0: C++ base class specifier=class A:14:7 [access=public isVirtual=false]
|
||||||
|
// CHECK: <invalid loc>:0:0: C++ base class specifier=class B:18:7 [access=private isVirtual=false]
|
||||||
|
// CHECK: load-stmts.cpp:23:8: CXXMethod=doC:23:8 Extent=[23:8 - 23:13]
|
||||||
|
// CHECK: load-stmts.cpp:26:7: ClassDecl=D:26:7 (Definition) Extent=[26:1 - 26:49]
|
||||||
|
// CHECK: <invalid loc>:0:0: C++ base class specifier=class C:22:7 [access=public isVirtual=true]
|
||||||
|
// CHECK: <invalid loc>:0:0: C++ base class specifier=class A:14:7 [access=private isVirtual=true]
|
||||||
|
|
||||||
|
|
|
@ -204,6 +204,26 @@ static void PrintCursor(CXCursor Cursor) {
|
||||||
printf(" [IBOutletCollection=%s]", clang_getCString(S));
|
printf(" [IBOutletCollection=%s]", clang_getCString(S));
|
||||||
clang_disposeString(S);
|
clang_disposeString(S);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Cursor.kind == CXCursor_CXXBaseSpecifier) {
|
||||||
|
enum CX_CXXAccessSpecifier access = clang_getCXXAccessSpecifier(Cursor);
|
||||||
|
unsigned isVirtual = clang_isVirtualBase(Cursor);
|
||||||
|
const char *accessStr = 0;
|
||||||
|
|
||||||
|
switch (access) {
|
||||||
|
case CX_CXXInvalidAccessSpecifier:
|
||||||
|
accessStr = "invalid"; break;
|
||||||
|
case CX_CXXPublic:
|
||||||
|
accessStr = "public"; break;
|
||||||
|
case CX_CXXProtected:
|
||||||
|
accessStr = "protected"; break;
|
||||||
|
case CX_CXXPrivate:
|
||||||
|
accessStr = "private"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" [access=%s isVirtual=%s]", accessStr,
|
||||||
|
isVirtual ? "true" : "false");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -285,6 +285,7 @@ public:
|
||||||
// Declaration visitors
|
// Declaration visitors
|
||||||
bool VisitAttributes(Decl *D);
|
bool VisitAttributes(Decl *D);
|
||||||
bool VisitBlockDecl(BlockDecl *B);
|
bool VisitBlockDecl(BlockDecl *B);
|
||||||
|
bool VisitCXXRecordDecl(CXXRecordDecl *D);
|
||||||
bool VisitDeclContext(DeclContext *DC);
|
bool VisitDeclContext(DeclContext *DC);
|
||||||
bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
|
bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
|
||||||
bool VisitTypedefDecl(TypedefDecl *D);
|
bool VisitTypedefDecl(TypedefDecl *D);
|
||||||
|
@ -1080,6 +1081,19 @@ bool CursorVisitor::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {
|
||||||
|
if (D->isDefinition()) {
|
||||||
|
for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
|
||||||
|
E = D->bases_end(); I != E; ++I) {
|
||||||
|
if (Visit(cxcursor::MakeCursorCXXBaseSpecifier(I, TU)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return VisitTagDecl(D);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CursorVisitor::VisitBlockExpr(BlockExpr *B) {
|
bool CursorVisitor::VisitBlockExpr(BlockExpr *B) {
|
||||||
return Visit(B->getBlockDecl());
|
return Visit(B->getBlockDecl());
|
||||||
}
|
}
|
||||||
|
@ -1825,6 +1839,10 @@ CXString clang_getCursorSpelling(CXCursor C) {
|
||||||
assert(OID && "getCursorSpelling(): Missing protocol decl");
|
assert(OID && "getCursorSpelling(): Missing protocol decl");
|
||||||
return createCXString(OID->getIdentifier()->getNameStart());
|
return createCXString(OID->getIdentifier()->getNameStart());
|
||||||
}
|
}
|
||||||
|
case CXCursor_CXXBaseSpecifier: {
|
||||||
|
CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
|
||||||
|
return createCXString(B->getType().getAsString());
|
||||||
|
}
|
||||||
case CXCursor_TypeRef: {
|
case CXCursor_TypeRef: {
|
||||||
TypeDecl *Type = getCursorTypeRef(C).first;
|
TypeDecl *Type = getCursorTypeRef(C).first;
|
||||||
assert(Type && "Missing type decl");
|
assert(Type && "Missing type decl");
|
||||||
|
@ -1953,6 +1971,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
|
||||||
return createCXString("Namespace");
|
return createCXString("Namespace");
|
||||||
case CXCursor_LinkageSpec:
|
case CXCursor_LinkageSpec:
|
||||||
return createCXString("LinkageSpec");
|
return createCXString("LinkageSpec");
|
||||||
|
case CXCursor_CXXBaseSpecifier:
|
||||||
|
return createCXString("C++ base class specifier");
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm_unreachable("Unhandled CXCursorKind");
|
llvm_unreachable("Unhandled CXCursorKind");
|
||||||
|
@ -2077,6 +2097,11 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) {
|
||||||
return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
|
return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case CXCursor_CXXBaseSpecifier: {
|
||||||
|
// FIXME: Figure out what location to return for a CXXBaseSpecifier.
|
||||||
|
return clang_getNullLocation();
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// FIXME: Need a way to enumerate all non-reference cases.
|
// FIXME: Need a way to enumerate all non-reference cases.
|
||||||
llvm_unreachable("Missed a reference kind");
|
llvm_unreachable("Missed a reference kind");
|
||||||
|
@ -2130,6 +2155,10 @@ static SourceRange getRawCursorExtent(CXCursor C) {
|
||||||
case CXCursor_TypeRef:
|
case CXCursor_TypeRef:
|
||||||
return getCursorTypeRef(C).second;
|
return getCursorTypeRef(C).second;
|
||||||
|
|
||||||
|
case CXCursor_CXXBaseSpecifier:
|
||||||
|
// FIXME: Figure out what source range to use for a CXBaseSpecifier.
|
||||||
|
return SourceRange();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// FIXME: Need a way to enumerate all non-reference cases.
|
// FIXME: Need a way to enumerate all non-reference cases.
|
||||||
llvm_unreachable("Missed a reference kind");
|
llvm_unreachable("Missed a reference kind");
|
||||||
|
@ -2203,6 +2232,12 @@ CXCursor clang_getCursorReferenced(CXCursor C) {
|
||||||
case CXCursor_TypeRef:
|
case CXCursor_TypeRef:
|
||||||
return MakeCXCursor(getCursorTypeRef(C).first, CXXUnit);
|
return MakeCXCursor(getCursorTypeRef(C).first, CXXUnit);
|
||||||
|
|
||||||
|
case CXCursor_CXXBaseSpecifier: {
|
||||||
|
CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C);
|
||||||
|
return clang_getTypeDeclaration(cxtype::MakeCXType(B->getType(),
|
||||||
|
CXXUnit));
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// We would prefer to enumerate all non-reference cursor kinds here.
|
// We would prefer to enumerate all non-reference cursor kinds here.
|
||||||
llvm_unreachable("Unhandled reference cursor kind");
|
llvm_unreachable("Unhandled reference cursor kind");
|
||||||
|
|
|
@ -21,6 +21,7 @@ set( LLVM_LINK_COMPONENTS
|
||||||
|
|
||||||
add_clang_library(libclang
|
add_clang_library(libclang
|
||||||
CIndex.cpp
|
CIndex.cpp
|
||||||
|
CIndexCXX.cpp
|
||||||
CIndexCodeCompletion.cpp
|
CIndexCodeCompletion.cpp
|
||||||
CIndexDiagnostic.cpp
|
CIndexDiagnostic.cpp
|
||||||
CIndexInclusionStack.cpp
|
CIndexInclusionStack.cpp
|
||||||
|
|
|
@ -302,6 +302,16 @@ cxcursor::getCursorTypeRef(CXCursor C) {
|
||||||
reinterpret_cast<uintptr_t>(C.data[1])));
|
reinterpret_cast<uintptr_t>(C.data[1])));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CXCursor cxcursor::MakeCursorCXXBaseSpecifier(CXXBaseSpecifier *B, ASTUnit *TU){
|
||||||
|
CXCursor C = { CXCursor_CXXBaseSpecifier, { B, 0, TU } };
|
||||||
|
return C;
|
||||||
|
}
|
||||||
|
|
||||||
|
CXXBaseSpecifier *cxcursor::getCursorCXXBaseSpecifier(CXCursor C) {
|
||||||
|
assert(C.kind == CXCursor_CXXBaseSpecifier);
|
||||||
|
return static_cast<CXXBaseSpecifier*>(C.data[0]);
|
||||||
|
}
|
||||||
|
|
||||||
CXCursor cxcursor::MakePreprocessingDirectiveCursor(SourceRange Range,
|
CXCursor cxcursor::MakePreprocessingDirectiveCursor(SourceRange Range,
|
||||||
ASTUnit *TU) {
|
ASTUnit *TU) {
|
||||||
CXCursor C = { CXCursor_PreprocessingDirective,
|
CXCursor C = { CXCursor_PreprocessingDirective,
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace clang {
|
||||||
class ASTContext;
|
class ASTContext;
|
||||||
class ASTUnit;
|
class ASTUnit;
|
||||||
class Attr;
|
class Attr;
|
||||||
|
class CXXBaseSpecifier;
|
||||||
class Decl;
|
class Decl;
|
||||||
class Expr;
|
class Expr;
|
||||||
class MacroDefinition;
|
class MacroDefinition;
|
||||||
|
@ -75,6 +76,12 @@ CXCursor MakeCursorTypeRef(TypeDecl *Type, SourceLocation Loc, ASTUnit *TU);
|
||||||
/// and optionally the location where the reference occurred.
|
/// and optionally the location where the reference occurred.
|
||||||
std::pair<TypeDecl *, SourceLocation> getCursorTypeRef(CXCursor C);
|
std::pair<TypeDecl *, SourceLocation> getCursorTypeRef(CXCursor C);
|
||||||
|
|
||||||
|
/// \brief Create a CXX base specifier cursor.
|
||||||
|
CXCursor MakeCursorCXXBaseSpecifier(CXXBaseSpecifier *B, ASTUnit *TU);
|
||||||
|
|
||||||
|
/// \brief Unpack a CXXBaseSpecifier cursor into a CXXBaseSpecifier.
|
||||||
|
CXXBaseSpecifier *getCursorCXXBaseSpecifier(CXCursor C);
|
||||||
|
|
||||||
/// \brief Create a preprocessing directive cursor.
|
/// \brief Create a preprocessing directive cursor.
|
||||||
CXCursor MakePreprocessingDirectiveCursor(SourceRange Range, ASTUnit *TU);
|
CXCursor MakePreprocessingDirectiveCursor(SourceRange Range, ASTUnit *TU);
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ _clang_createIndex
|
||||||
_clang_createTranslationUnit
|
_clang_createTranslationUnit
|
||||||
_clang_createTranslationUnitFromSourceFile
|
_clang_createTranslationUnitFromSourceFile
|
||||||
_clang_defaultCodeCompleteOptions
|
_clang_defaultCodeCompleteOptions
|
||||||
_clang_defaultEditingTranslationUnitOptions
|
|
||||||
_clang_defaultDiagnosticDisplayOptions
|
_clang_defaultDiagnosticDisplayOptions
|
||||||
|
_clang_defaultEditingTranslationUnitOptions
|
||||||
_clang_defaultReparseOptions
|
_clang_defaultReparseOptions
|
||||||
_clang_defaultSaveOptions
|
_clang_defaultSaveOptions
|
||||||
_clang_disposeCodeCompleteResults
|
_clang_disposeCodeCompleteResults
|
||||||
|
@ -30,7 +30,7 @@ _clang_equalLocations
|
||||||
_clang_equalTypes
|
_clang_equalTypes
|
||||||
_clang_formatDiagnostic
|
_clang_formatDiagnostic
|
||||||
_clang_getCString
|
_clang_getCString
|
||||||
_clang_getIBOutletCollectionType
|
_clang_getCXXAccessSpecifier
|
||||||
_clang_getCanonicalType
|
_clang_getCanonicalType
|
||||||
_clang_getClangVersion
|
_clang_getClangVersion
|
||||||
_clang_getCompletionAvailability
|
_clang_getCompletionAvailability
|
||||||
|
@ -48,8 +48,8 @@ _clang_getCursorLanguage
|
||||||
_clang_getCursorLinkage
|
_clang_getCursorLinkage
|
||||||
_clang_getCursorLocation
|
_clang_getCursorLocation
|
||||||
_clang_getCursorReferenced
|
_clang_getCursorReferenced
|
||||||
_clang_getCursorSpelling
|
|
||||||
_clang_getCursorResultType
|
_clang_getCursorResultType
|
||||||
|
_clang_getCursorSpelling
|
||||||
_clang_getCursorType
|
_clang_getCursorType
|
||||||
_clang_getCursorUSR
|
_clang_getCursorUSR
|
||||||
_clang_getDefinitionSpellingAndExtent
|
_clang_getDefinitionSpellingAndExtent
|
||||||
|
@ -64,6 +64,7 @@ _clang_getDiagnosticSpelling
|
||||||
_clang_getFile
|
_clang_getFile
|
||||||
_clang_getFileName
|
_clang_getFileName
|
||||||
_clang_getFileTime
|
_clang_getFileTime
|
||||||
|
_clang_getIBOutletCollectionType
|
||||||
_clang_getInclusions
|
_clang_getInclusions
|
||||||
_clang_getInstantiationLocation
|
_clang_getInstantiationLocation
|
||||||
_clang_getLocation
|
_clang_getLocation
|
||||||
|
@ -89,12 +90,13 @@ _clang_isCursorDefinition
|
||||||
_clang_isDeclaration
|
_clang_isDeclaration
|
||||||
_clang_isExpression
|
_clang_isExpression
|
||||||
_clang_isInvalid
|
_clang_isInvalid
|
||||||
_clang_isPreprocessing
|
|
||||||
_clang_isPODType
|
_clang_isPODType
|
||||||
|
_clang_isPreprocessing
|
||||||
_clang_isReference
|
_clang_isReference
|
||||||
_clang_isStatement
|
_clang_isStatement
|
||||||
_clang_isTranslationUnit
|
_clang_isTranslationUnit
|
||||||
_clang_isUnexposed
|
_clang_isUnexposed
|
||||||
|
_clang_isVirtualBase
|
||||||
_clang_parseTranslationUnit
|
_clang_parseTranslationUnit
|
||||||
_clang_reparseTranslationUnit
|
_clang_reparseTranslationUnit
|
||||||
_clang_saveTranslationUnit
|
_clang_saveTranslationUnit
|
||||||
|
|
|
@ -30,6 +30,7 @@ clang_equalLocations
|
||||||
clang_equalTypes
|
clang_equalTypes
|
||||||
clang_formatDiagnostic
|
clang_formatDiagnostic
|
||||||
clang_getCString
|
clang_getCString
|
||||||
|
clang_getCXXAccessSpecifier
|
||||||
clang_getCanonicalType
|
clang_getCanonicalType
|
||||||
clang_getClangVersion
|
clang_getClangVersion
|
||||||
clang_getCompletionAvailability
|
clang_getCompletionAvailability
|
||||||
|
@ -95,6 +96,7 @@ clang_isReference
|
||||||
clang_isStatement
|
clang_isStatement
|
||||||
clang_isTranslationUnit
|
clang_isTranslationUnit
|
||||||
clang_isUnexposed
|
clang_isUnexposed
|
||||||
|
clang_isVirtualBase
|
||||||
clang_parseTranslationUnit
|
clang_parseTranslationUnit
|
||||||
clang_reparseTranslationUnit
|
clang_reparseTranslationUnit
|
||||||
clang_saveTranslationUnit
|
clang_saveTranslationUnit
|
||||||
|
|
Loading…
Reference in New Issue