/// \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.
/// \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.
/// 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;
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;
NNS = nullptr;
}
} else {
- NNS = createNestedNameSpecifierForScopeOf(Ctx, ArgTDecl, true);
+ NNS = createNestedNameSpecifierForScopeOf(
+ Ctx, ArgTDecl, true, WithGlobalNsPrefix);
}
if (NNS) {
TName = Ctx.getQualifiedTemplateName(NNS,
}
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
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;
}
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.
// Cheap to copy and potentially modified by
// getFullyQualifedTemplateArgument.
TemplateArgument Arg(*I);
- MightHaveChanged |= getFullyQualifiedTemplateArgument(Ctx, Arg);
+ MightHaveChanged |= getFullyQualifiedTemplateArgument(
+ Ctx, Arg, WithGlobalNsPrefix);
FQArgs.push_back(Arg);
}
// 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);
}
}
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: {
}
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;
}
/// \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();
}
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;
// accessible at the end of the TU.
return nullptr;
}
+ } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) {
+ return NestedNameSpecifier::GlobalSpecifier(Ctx);
}
return nullptr;
}
/// \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;
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());
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);
// 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)
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.
// 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) {
}
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);
}