Implement libclang support for using directives (cursor + visitation +

suppressing USRs). Also, fix up the source location information for
using directives so that the declaration location refers to the
namespace name.

llvm-svn: 112693
This commit is contained in:
Douglas Gregor 2010-09-01 03:07:18 +00:00
parent 110ed64fbb
commit 01a430134f
10 changed files with 54 additions and 54 deletions

View File

@ -996,8 +996,11 @@ enum CXCursorKind {
CXCursor_ClassTemplatePartialSpecialization = 32,
/** \brief A C++ namespace alias declaration. */
CXCursor_NamespaceAlias = 33,
/** \brief A C++ using directive. */
CXCursor_UsingDirective = 34,
CXCursor_FirstDecl = CXCursor_UnexposedDecl,
CXCursor_LastDecl = CXCursor_NamespaceAlias,
CXCursor_LastDecl = CXCursor_UsingDirective,
/* References */
CXCursor_FirstRef = 40, /* Decl references */

View File

@ -1707,7 +1707,9 @@ public:
// artificial name, for all using-directives in order to store
// them in DeclContext effectively.
class UsingDirectiveDecl : public NamedDecl {
/// \brief The location of the "using" keyword.
SourceLocation UsingLoc;
/// SourceLocation - Location of 'namespace' token.
SourceLocation NamespaceLoc;
@ -1719,10 +1721,6 @@ class UsingDirectiveDecl : public NamedDecl {
/// name, if any.
NestedNameSpecifier *Qualifier;
/// IdentLoc - Location of nominated namespace-name identifier.
// FIXME: We don't store location of scope specifier.
SourceLocation IdentLoc;
/// NominatedNamespace - Namespace nominated by using-directive.
NamedDecl *NominatedNamespace;
@ -1737,17 +1735,16 @@ class UsingDirectiveDecl : public NamedDecl {
return DeclarationName::getUsingDirectiveName();
}
UsingDirectiveDecl(DeclContext *DC, SourceLocation L,
UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc,
SourceLocation NamespcLoc,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc,
NamedDecl *Nominated,
DeclContext *CommonAncestor)
: NamedDecl(UsingDirective, DC, L, getName()),
: NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc),
NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange),
Qualifier(Qualifier), IdentLoc(IdentLoc),
NominatedNamespace(Nominated),
Qualifier(Qualifier), NominatedNamespace(Nominated),
CommonAncestor(CommonAncestor) {
}
@ -1756,18 +1753,10 @@ public:
/// that qualifies the namespace name.
SourceRange getQualifierRange() const { return QualifierRange; }
/// \brief Set the source range of the nested-name-specifier that
/// qualifies the namespace name.
void setQualifierRange(SourceRange R) { QualifierRange = R; }
/// \brief Retrieve the nested-name-specifier that qualifies the
/// name of the namespace.
NestedNameSpecifier *getQualifier() const { return Qualifier; }
/// \brief Set the nested-name-specifier that qualifes the name of the
/// namespace.
void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; }
const NamedDecl *getNominatedNamespaceAsWritten() const {
return NominatedNamespace;
@ -1780,34 +1769,23 @@ public:
return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace();
}
/// setNominatedNamespace - Set the namespace nominataed by the
/// using-directive.
void setNominatedNamespace(NamedDecl* NS);
/// \brief Returns the common ancestor context of this using-directive and
/// its nominated namespace.
DeclContext *getCommonAncestor() { return CommonAncestor; }
const DeclContext *getCommonAncestor() const { return CommonAncestor; }
/// \brief Set the common ancestor context of this using-directive and its
/// nominated namespace.
void setCommonAncestor(DeclContext* Cxt) { CommonAncestor = Cxt; }
/// \brief Return the location of the "using" keyword.
SourceLocation getUsingLoc() const { return UsingLoc; }
// FIXME: Could omit 'Key' in name.
/// getNamespaceKeyLocation - Returns location of namespace keyword.
SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; }
/// setNamespaceKeyLocation - Set the the location of the namespacekeyword.
void setNamespaceKeyLocation(SourceLocation L) { NamespaceLoc = L; }
/// getIdentLocation - Returns location of identifier.
SourceLocation getIdentLocation() const { return IdentLoc; }
/// setIdentLocation - set the location of the identifier.
void setIdentLocation(SourceLocation L) { IdentLoc = L; }
SourceLocation getIdentLocation() const { return getLocation(); }
static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
SourceLocation UsingLoc,
SourceLocation NamespaceLoc,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
@ -1815,12 +1793,18 @@ public:
NamedDecl *Nominated,
DeclContext *CommonAncestor);
SourceRange getSourceRange() const {
return SourceRange(UsingLoc, getLocation());
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UsingDirectiveDecl *D) { return true; }
static bool classofKind(Kind K) { return K == UsingDirective; }
// Friend for getUsingDirectiveName.
friend class DeclContext;
friend class ASTDeclReader;
};
/// NamespaceAliasDecl - Represents a C++ namespace alias. For example:

View File

@ -989,14 +989,8 @@ NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() {
return cast_or_null<NamespaceDecl>(NominatedNamespace);
}
void UsingDirectiveDecl::setNominatedNamespace(NamedDecl* ND) {
assert((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
"expected a NamespaceDecl or NamespaceAliasDecl");
NominatedNamespace = ND;
}
NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
SourceLocation UsingLoc,
SourceLocation AliasLoc,
IdentifierInfo *Alias,
SourceRange QualifierRange,
@ -1005,7 +999,7 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
NamedDecl *Namespace) {
if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
Namespace = NS->getOriginalNamespace();
return new (C) NamespaceAliasDecl(DC, L, AliasLoc, Alias, QualifierRange,
return new (C) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias, QualifierRange,
Qualifier, IdentLoc, Namespace);
}

View File

@ -676,13 +676,12 @@ void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
VisitNamedDecl(D);
D->setNamespaceKeyLocation(Reader.ReadSourceLocation(Record, Idx));
D->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
D->setIdentLocation(Reader.ReadSourceLocation(Record, Idx));
D->setNominatedNamespace(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
D->setCommonAncestor(cast_or_null<DeclContext>(
Reader.GetDecl(Record[Idx++])));
D->UsingLoc = Reader.ReadSourceLocation(Record, Idx);
D->NamespaceLoc = Reader.ReadSourceLocation(Record, Idx);
D->QualifierRange = Reader.ReadSourceRange(Record, Idx);
D->Qualifier = Reader.ReadNestedNameSpecifier(Record, Idx);
D->NominatedNamespace = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
D->CommonAncestor = cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++]));
}
void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {

View File

@ -658,10 +658,10 @@ void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) {
void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
VisitNamedDecl(D);
Writer.AddSourceLocation(D->getUsingLoc(), Record);
Writer.AddSourceLocation(D->getNamespaceKeyLocation(), Record);
Writer.AddSourceRange(D->getQualifierRange(), Record);
Writer.AddNestedNameSpecifier(D->getQualifier(), Record);
Writer.AddSourceLocation(D->getIdentLocation(), Record);
Writer.AddDeclRef(D->getNominatedNamespace(), Record);
Writer.AddDeclRef(dyn_cast<Decl>(D->getCommonAncestor()), Record);
Code = serialization::DECL_USING_DIRECTIVE;

View File

@ -13,7 +13,7 @@ namespace std {
namespace std98 = std;
namespace std0x = std98;
// FIXME: using directives
using namespace std0x;
// RUN: c-index-test -test-load-source all %s | FileCheck %s
// CHECK: load-namespaces.cpp:3:11: Namespace=std:3:11 (Definition) Extent=[3:11 - 7:2]
@ -25,3 +25,5 @@ namespace std0x = std98;
// CHECK: load-namespaces.cpp:13:19: NamespaceRef=std:3:11 Extent=[13:19 - 13:22]
// CHECK: load-namespaces.cpp:14:11: NamespaceAlias=std0x:14:11 Extent=[14:1 - 14:24]
// CHECK: load-namespaces.cpp:14:19: NamespaceRef=std98:13:11 Extent=[14:19 - 14:24]
// CHECK: load-namespaces.cpp:16:17: UsingDirective=:16:17 Extent=[16:1 - 16:22]
// CHECK: load-namespaces.cpp:16:17: NamespaceRef=std0x:14:11 Extent=[16:17 - 16:22]

View File

@ -57,6 +57,8 @@ extern "C" {
namespace foo_alias = foo;
using namespace foo;
// RUN: c-index-test -test-load-source-usrs all %s | FileCheck %s
// CHECK: usrs.cpp c:@N@foo Extent=[1:11 - 4:2]
// CHECK: usrs.cpp c:@N@foo@x Extent=[2:3 - 2:8]

View File

@ -317,7 +317,8 @@ public:
bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
bool VisitNamespaceDecl(NamespaceDecl *D);
bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
// Name visitor
bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
@ -871,6 +872,13 @@ bool CursorVisitor::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
D->getTargetNameLoc(), TU));
}
bool CursorVisitor::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
// FIXME: Visit nested-name-specifier
return Visit(MakeCursorNamespaceRef(D->getNominatedNamespaceAsWritten(),
D->getIdentLocation(), TU));
}
bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
switch (Name.getName().getNameKind()) {
case clang::DeclarationName::Identifier:
@ -2022,6 +2030,9 @@ static CXString getDeclSpelling(Decl *D) {
// ObjCCategoryImplDecl returns the category name.
return createCXString(CIMP->getIdentifier()->getNameStart());
if (isa<UsingDirectiveDecl>(D))
return createCXString("");
llvm::SmallString<1024> S;
llvm::raw_svector_ostream os(S);
ND->printName(os);
@ -2219,6 +2230,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return createCXString("ClassTemplatePartialSpecialization");
case CXCursor_NamespaceAlias:
return createCXString("NamespaceAlias");
case CXCursor_UsingDirective:
return createCXString("UsingDirective");
}
llvm_unreachable("Unhandled CXCursorKind");

View File

@ -82,9 +82,11 @@ public:
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
void VisitLinkageSpecDecl(LinkageSpecDecl *D) {
IgnoreResults = true;
return;
}
void VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
IgnoreResults = true;
}
/// Generate the string component containing the location of the
/// declaration.
bool GenLoc(const Decl *D);

View File

@ -69,6 +69,7 @@ static CXCursorKind GetCursorKind(Decl *D) {
case Decl::ClassTemplate: return CXCursor_ClassTemplate;
case Decl::ClassTemplatePartialSpecialization:
return CXCursor_ClassTemplatePartialSpecialization;
case Decl::UsingDirective: return CXCursor_UsingDirective;
default:
if (TagDecl *TD = dyn_cast<TagDecl>(D)) {