r274185 - [Tooling] Add optional argument to getFullyQualifiedName to prepend "::".
Siva Chandra via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 29 15:38:59 PDT 2016
Author: sivachandra
Date: Wed Jun 29 17:38:59 2016
New Revision: 274185
URL: http://llvm.org/viewvc/llvm-project?rev=274185&view=rev
Log:
[Tooling] Add optional argument to getFullyQualifiedName to prepend "::".
Reviewers: rsmith, saugustine, rnk
Subscribers: klimek, cfe-commits
Differential Revision: http://reviews.llvm.org/D21666
Modified:
cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h
cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp
cfe/trunk/unittests/Tooling/QualTypeNamesTest.cpp
Modified: cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h?rev=274185&r1=274184&r2=274185&view=diff
==============================================================================
--- cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h (original)
+++ cfe/trunk/include/clang/Tooling/Core/QualTypeNames.h Wed Jun 29 17:38:59 2016
@@ -69,8 +69,11 @@ namespace TypeName {
/// \param[in] QT - the type for which the fully qualified name will be
/// returned.
/// \param[in] Ctx - the ASTContext to be used.
+/// \param[in] WithGlobalNsPrefix - If true, then the global namespace
+/// specifier "::" will be prepended to the fully qualified name.
std::string getFullyQualifiedName(QualType QT,
- const ASTContext &Ctx);
+ const ASTContext &Ctx,
+ bool WithGlobalNsPrefix = false);
} // end namespace TypeName
} // end namespace clang
#endif // LLVM_CLANG_TOOLING_CORE_QUALTYPENAMES_H
Modified: cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp?rev=274185&r1=274184&r2=274185&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp (original)
+++ cfe/trunk/lib/Tooling/Core/QualTypeNames.cpp Wed Jun 29 17:38:59 2016
@@ -30,7 +30,10 @@ namespace TypeName {
/// \param[in] QT - the type for which the fully qualified type will be
/// returned.
/// \param[in] Ctx - the ASTContext to be used.
-static QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx);
+/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
+/// specifier "::" should be prepended or not.
+static QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
+ bool WithGlobalNsPrefix);
/// \brief Create a NestedNameSpecifier for Namesp and its enclosing
/// scopes.
@@ -38,8 +41,12 @@ static QualType getFullyQualifiedType(Qu
/// \param[in] Ctx - the AST Context to be used.
/// \param[in] Namesp - the NamespaceDecl for which a NestedNameSpecifier
/// is requested.
+/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
+/// specifier "::" should be prepended or not.
static NestedNameSpecifier *createNestedNameSpecifier(
- const ASTContext &Ctx, const NamespaceDecl *Namesp);
+ const ASTContext &Ctx,
+ const NamespaceDecl *Namesp,
+ bool WithGlobalNsPrefix);
/// \brief Create a NestedNameSpecifier for TagDecl and its enclosing
/// scopes.
@@ -49,17 +56,22 @@ static NestedNameSpecifier *createNested
/// requested.
/// \param[in] FullyQualify - Convert all template arguments into fully
/// qualified names.
+/// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace
+/// specifier "::" should be prepended or not.
static NestedNameSpecifier *createNestedNameSpecifier(
- const ASTContext &Ctx, const TypeDecl *TD, bool FullyQualify);
+ const ASTContext &Ctx, const TypeDecl *TD,
+ bool FullyQualify, bool WithGlobalNsPrefix);
static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
- const ASTContext &Ctx, const Decl *decl, bool FullyQualified);
+ const ASTContext &Ctx, const Decl *decl,
+ bool FullyQualified, bool WithGlobalNsPrefix);
static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
- const ASTContext &Ctx, NestedNameSpecifier *scope);
+ const ASTContext &Ctx, NestedNameSpecifier *scope, bool WithGlobalNsPrefix);
static bool getFullyQualifiedTemplateName(const ASTContext &Ctx,
- TemplateName &TName) {
+ TemplateName &TName,
+ bool WithGlobalNsPrefix) {
bool Changed = false;
NestedNameSpecifier *NNS = nullptr;
@@ -71,7 +83,8 @@ static bool getFullyQualifiedTemplateNam
if (QTName && !QTName->hasTemplateKeyword()) {
NNS = QTName->getQualifier();
- NestedNameSpecifier *QNNS = getFullyQualifiedNestedNameSpecifier(Ctx, NNS);
+ NestedNameSpecifier *QNNS = getFullyQualifiedNestedNameSpecifier(
+ Ctx, NNS, WithGlobalNsPrefix);
if (QNNS != NNS) {
Changed = true;
NNS = QNNS;
@@ -79,7 +92,8 @@ static bool getFullyQualifiedTemplateNam
NNS = nullptr;
}
} else {
- NNS = createNestedNameSpecifierForScopeOf(Ctx, ArgTDecl, true);
+ NNS = createNestedNameSpecifierForScopeOf(
+ Ctx, ArgTDecl, true, WithGlobalNsPrefix);
}
if (NNS) {
TName = Ctx.getQualifiedTemplateName(NNS,
@@ -90,7 +104,8 @@ static bool getFullyQualifiedTemplateNam
}
static bool getFullyQualifiedTemplateArgument(const ASTContext &Ctx,
- TemplateArgument &Arg) {
+ TemplateArgument &Arg,
+ bool WithGlobalNsPrefix) {
bool Changed = false;
// Note: we do not handle TemplateArgument::Expression, to replace it
@@ -98,14 +113,14 @@ static bool getFullyQualifiedTemplateArg
if (Arg.getKind() == TemplateArgument::Template) {
TemplateName TName = Arg.getAsTemplate();
- Changed = getFullyQualifiedTemplateName(Ctx, TName);
+ Changed = getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix);
if (Changed) {
Arg = TemplateArgument(TName);
}
} else if (Arg.getKind() == TemplateArgument::Type) {
QualType SubTy = Arg.getAsType();
// Check if the type needs more desugaring and recurse.
- QualType QTFQ = getFullyQualifiedType(SubTy, Ctx);
+ QualType QTFQ = getFullyQualifiedType(SubTy, Ctx, WithGlobalNsPrefix);
if (QTFQ != SubTy) {
Arg = TemplateArgument(QTFQ);
Changed = true;
@@ -115,7 +130,8 @@ static bool getFullyQualifiedTemplateArg
}
static const Type *getFullyQualifiedTemplateType(const ASTContext &Ctx,
- const Type *TypePtr) {
+ const Type *TypePtr,
+ bool WithGlobalNsPrefix) {
// DependentTemplateTypes exist within template declarations and
// definitions. Therefore we shouldn't encounter them at the end of
// a translation unit. If we do, the caller has made an error.
@@ -130,7 +146,8 @@ static const Type *getFullyQualifiedTemp
// Cheap to copy and potentially modified by
// getFullyQualifedTemplateArgument.
TemplateArgument Arg(*I);
- MightHaveChanged |= getFullyQualifiedTemplateArgument(Ctx, Arg);
+ MightHaveChanged |= getFullyQualifiedTemplateArgument(
+ Ctx, Arg, WithGlobalNsPrefix);
FQArgs.push_back(Arg);
}
@@ -160,7 +177,8 @@ static const Type *getFullyQualifiedTemp
// cheap to copy and potentially modified by
// getFullyQualifedTemplateArgument
TemplateArgument Arg(TemplateArgs[I]);
- MightHaveChanged |= getFullyQualifiedTemplateArgument(Ctx, Arg);
+ MightHaveChanged |= getFullyQualifiedTemplateArgument(
+ Ctx, Arg, WithGlobalNsPrefix);
FQArgs.push_back(Arg);
}
@@ -182,44 +200,55 @@ static const Type *getFullyQualifiedTemp
}
static NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D,
- bool FullyQualify) {
+ bool FullyQualify,
+ bool WithGlobalNsPrefix) {
const DeclContext *DC = D->getDeclContext();
if (const auto *NS = dyn_cast<NamespaceDecl>(DC)) {
while (NS && NS->isInline()) {
// Ignore inline namespace;
NS = dyn_cast<NamespaceDecl>(NS->getDeclContext());
}
- if (NS->getDeclName()) return createNestedNameSpecifier(Ctx, NS);
+ if (NS->getDeclName()) {
+ return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix);
+ }
return nullptr; // no starting '::', no anonymous
} else if (const auto *TD = dyn_cast<TagDecl>(DC)) {
- return createNestedNameSpecifier(Ctx, TD, FullyQualify);
+ return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix);
} else if (const auto *TDD = dyn_cast<TypedefNameDecl>(DC)) {
- return createNestedNameSpecifier(Ctx, TDD, FullyQualify);
+ return createNestedNameSpecifier(
+ Ctx, TDD, FullyQualify, WithGlobalNsPrefix);
+ } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
+ return NestedNameSpecifier::GlobalSpecifier(Ctx);
}
- return nullptr; // no starting '::'
+ return nullptr; // no starting '::' if |WithGlobalNsPrefix| is false
}
/// \brief Return a fully qualified version of this name specifier.
static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
- const ASTContext &Ctx, NestedNameSpecifier *Scope) {
+ const ASTContext &Ctx, NestedNameSpecifier *Scope,
+ bool WithGlobalNsPrefix) {
switch (Scope->getKind()) {
case NestedNameSpecifier::Global:
// Already fully qualified
return Scope;
case NestedNameSpecifier::Namespace:
- return TypeName::createNestedNameSpecifier(Ctx, Scope->getAsNamespace());
+ return TypeName::createNestedNameSpecifier(
+ Ctx, Scope->getAsNamespace(), WithGlobalNsPrefix);
case NestedNameSpecifier::NamespaceAlias:
// Namespace aliases are only valid for the duration of the
// scope where they were introduced, and therefore are often
// invalid at the end of the TU. So use the namespace name more
// likely to be valid at the end of the TU.
return TypeName::createNestedNameSpecifier(
- Ctx, Scope->getAsNamespaceAlias()->getNamespace()->getCanonicalDecl());
+ Ctx,
+ Scope->getAsNamespaceAlias()->getNamespace()->getCanonicalDecl(),
+ WithGlobalNsPrefix);
case NestedNameSpecifier::Identifier:
// A function or some other construct that makes it un-namable
// at the end of the TU. Skip the current component of the name,
// but use the name of it's prefix.
- return getFullyQualifiedNestedNameSpecifier(Ctx, Scope->getPrefix());
+ return getFullyQualifiedNestedNameSpecifier(
+ Ctx, Scope->getPrefix(), WithGlobalNsPrefix);
case NestedNameSpecifier::Super:
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
@@ -233,10 +262,12 @@ static NestedNameSpecifier *getFullyQual
}
if (TD) {
return TypeName::createNestedNameSpecifier(Ctx, TD,
- true /*FullyQualified*/);
+ true /*FullyQualified*/,
+ WithGlobalNsPrefix);
} else if (const auto *TDD = dyn_cast<TypedefType>(Type)) {
return TypeName::createNestedNameSpecifier(Ctx, TDD->getDecl(),
- true /*FullyQualified*/);
+ true /*FullyQualified*/,
+ WithGlobalNsPrefix);
}
return Scope;
}
@@ -247,7 +278,8 @@ static NestedNameSpecifier *getFullyQual
/// \brief Create a nested name specifier for the declaring context of
/// the type.
static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
- const ASTContext &Ctx, const Decl *Decl, bool FullyQualified) {
+ const ASTContext &Ctx, const Decl *Decl,
+ bool FullyQualified, bool WithGlobalNsPrefix) {
assert(Decl);
const DeclContext *DC = Decl->getDeclContext()->getRedeclContext();
@@ -276,9 +308,10 @@ static NestedNameSpecifier *createNested
}
if (OuterNS) {
- return createNestedNameSpecifier(Ctx, OuterNS);
+ return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix);
} else if (const auto *TD = dyn_cast<TagDecl>(Outer)) {
- return createNestedNameSpecifier(Ctx, TD, FullyQualified);
+ return createNestedNameSpecifier(
+ Ctx, TD, FullyQualified, WithGlobalNsPrefix);
} else if (dyn_cast<TranslationUnitDecl>(Outer)) {
// Context is the TU. Nothing needs to be done.
return nullptr;
@@ -288,6 +321,8 @@ static NestedNameSpecifier *createNested
// accessible at the end of the TU.
return nullptr;
}
+ } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
+ return NestedNameSpecifier::GlobalSpecifier(Ctx);
}
return nullptr;
}
@@ -295,7 +330,8 @@ static NestedNameSpecifier *createNested
/// \brief Create a nested name specifier for the declaring context of
/// the type.
static NestedNameSpecifier *createNestedNameSpecifierForScopeOf(
- const ASTContext &Ctx, const Type *TypePtr, bool FullyQualified) {
+ const ASTContext &Ctx, const Type *TypePtr,
+ bool FullyQualified, bool WithGlobalNsPrefix) {
if (!TypePtr) return nullptr;
Decl *Decl = nullptr;
@@ -312,11 +348,13 @@ static NestedNameSpecifier *createNested
if (!Decl) return nullptr;
- return createNestedNameSpecifierForScopeOf(Ctx, Decl, FullyQualified);
+ return createNestedNameSpecifierForScopeOf(
+ Ctx, Decl, FullyQualified, WithGlobalNsPrefix);
}
-NestedNameSpecifier *createNestedNameSpecifier(
- const ASTContext &Ctx, const NamespaceDecl *Namespace) {
+NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx,
+ const NamespaceDecl *Namespace,
+ bool WithGlobalNsPrefix) {
while (Namespace && Namespace->isInline()) {
// Ignore inline namespace;
Namespace = dyn_cast<NamespaceDecl>(Namespace->getDeclContext());
@@ -325,25 +363,32 @@ NestedNameSpecifier *createNestedNameSpe
bool FullyQualified = true; // doesn't matter, DeclContexts are namespaces
return NestedNameSpecifier::Create(
- Ctx, createOuterNNS(Ctx, Namespace, FullyQualified), Namespace);
+ Ctx,
+ createOuterNNS(Ctx, Namespace, FullyQualified, WithGlobalNsPrefix),
+ Namespace);
}
-NestedNameSpecifier *createNestedNameSpecifier(
- const ASTContext &Ctx, const TypeDecl *TD, bool FullyQualify) {
- return NestedNameSpecifier::Create(Ctx, createOuterNNS(Ctx, TD, FullyQualify),
- false /*No TemplateKeyword*/,
- TD->getTypeForDecl());
+NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx,
+ const TypeDecl *TD,
+ bool FullyQualify,
+ bool WithGlobalNsPrefix) {
+ return NestedNameSpecifier::Create(
+ Ctx,
+ createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
+ false /*No TemplateKeyword*/,
+ TD->getTypeForDecl());
}
/// \brief Return the fully qualified type, including fully-qualified
/// versions of any template parameters.
-QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx) {
+QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
+ bool WithGlobalNsPrefix) {
// In case of myType* we need to strip the pointer first, fully
// qualify and attach the pointer once again.
if (isa<PointerType>(QT.getTypePtr())) {
// Get the qualifiers.
Qualifiers Quals = QT.getQualifiers();
- QT = getFullyQualifiedType(QT->getPointeeType(), Ctx);
+ QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
QT = Ctx.getPointerType(QT);
// Add back the qualifiers.
QT = Ctx.getQualifiedType(QT, Quals);
@@ -356,7 +401,7 @@ QualType getFullyQualifiedType(QualType
// Get the qualifiers.
bool IsLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr());
Qualifiers Quals = QT.getQualifiers();
- QT = getFullyQualifiedType(QT->getPointeeType(), Ctx);
+ QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix);
// Add the r- or l-value reference type back to the fully
// qualified one.
if (IsLValueRefTy)
@@ -394,10 +439,10 @@ QualType getFullyQualifiedType(QualType
assert(!QT.hasLocalQualifiers());
Keyword = ETypeInput->getKeyword();
}
- // Create a nested name specifier if needed (i.e. if the decl context
- // is not the global scope.
+ // Create a nested name specifier if needed.
Prefix = createNestedNameSpecifierForScopeOf(Ctx, QT.getTypePtr(),
- true /*FullyQualified*/);
+ true /*FullyQualified*/,
+ WithGlobalNsPrefix);
// In case of template specializations iterate over the arguments and
// fully qualify them as well.
@@ -407,7 +452,8 @@ QualType getFullyQualifiedType(QualType
// may point to a template specialization) or Template
// Specialization Type. We need to fully qualify their arguments.
- const Type *TypePtr = getFullyQualifiedTemplateType(Ctx, QT.getTypePtr());
+ const Type *TypePtr = getFullyQualifiedTemplateType(
+ Ctx, QT.getTypePtr(), WithGlobalNsPrefix);
QT = QualType(TypePtr, 0);
}
if (Prefix || Keyword != ETK_None) {
@@ -418,13 +464,14 @@ QualType getFullyQualifiedType(QualType
}
std::string getFullyQualifiedName(QualType QT,
- const ASTContext &Ctx) {
+ const ASTContext &Ctx,
+ bool WithGlobalNsPrefix) {
PrintingPolicy Policy(Ctx.getPrintingPolicy());
Policy.SuppressScope = false;
Policy.AnonymousTagLocations = false;
Policy.PolishForDeclaration = true;
Policy.SuppressUnwrittenScope = true;
- QualType FQQT = getFullyQualifiedType(QT, Ctx);
+ QualType FQQT = getFullyQualifiedType(QT, Ctx, WithGlobalNsPrefix);
return FQQT.getAsString(Policy);
}
Modified: cfe/trunk/unittests/Tooling/QualTypeNamesTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/QualTypeNamesTest.cpp?rev=274185&r1=274184&r2=274185&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/QualTypeNamesTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/QualTypeNamesTest.cpp Wed Jun 29 17:38:59 2016
@@ -14,6 +14,7 @@ using namespace clang;
namespace {
struct TypeNameVisitor : TestVisitor<TypeNameVisitor> {
llvm::StringMap<std::string> ExpectedQualTypeNames;
+ bool WithGlobalNsPrefix = false;
// ValueDecls are the least-derived decl with both a qualtype and a
// name.
@@ -26,7 +27,8 @@ struct TypeNameVisitor : TestVisitor<Typ
ExpectedQualTypeNames.lookup(VD->getNameAsString());
if (ExpectedName != "") {
std::string ActualName =
- TypeName::getFullyQualifiedName(VD->getType(), *Context);
+ TypeName::getFullyQualifiedName(VD->getType(), *Context,
+ WithGlobalNsPrefix);
if (ExpectedName != ActualName) {
// A custom message makes it much easier to see what declaration
// failed compared to EXPECT_EQ.
@@ -179,6 +181,42 @@ TEST(QualTypeNameTest, getFullyQualified
" TX CheckTX;"
" struct A { typedef int X; };"
"}");
+
+ TypeNameVisitor GlobalNsPrefix;
+ GlobalNsPrefix.WithGlobalNsPrefix = true;
+ GlobalNsPrefix.ExpectedQualTypeNames["IntVal"] = "int";
+ GlobalNsPrefix.ExpectedQualTypeNames["BoolVal"] = "bool";
+ GlobalNsPrefix.ExpectedQualTypeNames["XVal"] = "::A::B::X";
+ GlobalNsPrefix.ExpectedQualTypeNames["IntAliasVal"] = "::A::B::Alias<int>";
+ GlobalNsPrefix.ExpectedQualTypeNames["ZVal"] = "::A::B::Y::Z";
+ GlobalNsPrefix.ExpectedQualTypeNames["GlobalZVal"] = "::Z";
+ GlobalNsPrefix.ExpectedQualTypeNames["CheckK"] = "D::aStruct";
+ GlobalNsPrefix.runOver(
+ "namespace A {\n"
+ " namespace B {\n"
+ " int IntVal;\n"
+ " bool BoolVal;\n"
+ " struct X {};\n"
+ " X XVal;\n"
+ " template <typename T> class CCC { };\n"
+ " template <typename T>\n"
+ " using Alias = CCC<T>;\n"
+ " Alias<int> IntAliasVal;\n"
+ " struct Y { struct Z {}; };\n"
+ " Y::Z ZVal;\n"
+ " }\n"
+ "}\n"
+ "struct Z {};\n"
+ "Z GlobalZVal;\n"
+ "namespace {\n"
+ " namespace D {\n"
+ " namespace {\n"
+ " class aStruct {};\n"
+ " aStruct CheckK;\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ );
}
} // end anonymous namespace
More information about the cfe-commits
mailing list