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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112693 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index bbe9a4d..7e4902d 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -996,8 +996,11 @@
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 */
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index e259ccb..f5cbfd0 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -1707,7 +1707,9 @@
// 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 @@
/// 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 @@
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 @@
/// 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 @@
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 @@
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:
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index eed3702..f404155 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -989,14 +989,8 @@
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 @@
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);
}
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 512d4b5..cb6f29a 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -676,13 +676,12 @@
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) {
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index 90d135d..ce39a10 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -658,10 +658,10 @@
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;
diff --git a/test/Index/load-namespaces.cpp b/test/Index/load-namespaces.cpp
index e614f7c..9c8db0a 100644
--- a/test/Index/load-namespaces.cpp
+++ b/test/Index/load-namespaces.cpp
@@ -13,7 +13,7 @@
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 @@
// 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]
diff --git a/test/Index/usrs.cpp b/test/Index/usrs.cpp
index 3f50ea2..cacfdf2 100644
--- a/test/Index/usrs.cpp
+++ b/test/Index/usrs.cpp
@@ -57,6 +57,8 @@
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]
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 230631b..d849186 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -317,7 +317,8 @@
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 @@
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 @@
// 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 @@
return createCXString("ClassTemplatePartialSpecialization");
case CXCursor_NamespaceAlias:
return createCXString("NamespaceAlias");
+ case CXCursor_UsingDirective:
+ return createCXString("UsingDirective");
}
llvm_unreachable("Unhandled CXCursorKind");
diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp
index 9ef851a..5628aef 100644
--- a/tools/libclang/CIndexUSRs.cpp
+++ b/tools/libclang/CIndexUSRs.cpp
@@ -82,9 +82,11 @@
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);
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index 3edbc4d..75806ff 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -69,6 +69,7 @@
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)) {