mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-14 17:06:38 +00:00
[clang] improved preservation of template keyword (#133610)
This commit is contained in:
parent
3c7a0e6c82
commit
dc17429ae6
@ -119,8 +119,7 @@ getQualification(ASTContext &Context, const DeclContext *DestContext,
|
||||
// There can't be any more tag parents after hitting a namespace.
|
||||
assert(!ReachedNS);
|
||||
(void)ReachedNS;
|
||||
NNS = NestedNameSpecifier::Create(Context, nullptr, false,
|
||||
TD->getTypeForDecl());
|
||||
NNS = NestedNameSpecifier::Create(Context, nullptr, TD->getTypeForDecl());
|
||||
} else if (auto *NSD = llvm::dyn_cast<NamespaceDecl>(CurContext)) {
|
||||
ReachedNS = true;
|
||||
NNS = NestedNameSpecifier::Create(Context, nullptr, NSD);
|
||||
|
@ -1467,7 +1467,6 @@ bool allowIndex(CodeCompletionContext &CC) {
|
||||
return true;
|
||||
case NestedNameSpecifier::Super:
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
// Unresolved inside a template.
|
||||
case NestedNameSpecifier::Identifier:
|
||||
return false;
|
||||
|
@ -157,7 +157,6 @@ class DumpVisitor : public RecursiveASTVisitor<DumpVisitor> {
|
||||
NNS_KIND(Identifier);
|
||||
NNS_KIND(Namespace);
|
||||
NNS_KIND(TypeSpec);
|
||||
NNS_KIND(TypeSpecWithTemplate);
|
||||
NNS_KIND(Global);
|
||||
NNS_KIND(Super);
|
||||
NNS_KIND(NamespaceAlias);
|
||||
|
@ -500,7 +500,6 @@ public:
|
||||
}
|
||||
return;
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
add(QualType(NNS->getAsType(), 0), Flags);
|
||||
return;
|
||||
case NestedNameSpecifier::Global:
|
||||
|
@ -144,7 +144,6 @@ public:
|
||||
case NestedNameSpecifier::Global:
|
||||
return true;
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
case NestedNameSpecifier::Super:
|
||||
case NestedNameSpecifier::Identifier:
|
||||
return false;
|
||||
|
@ -275,6 +275,10 @@ Improvements to Clang's diagnostics
|
||||
- Diagnostics on chained comparisons (``a < b < c``) are now an error by default. This can be disabled with
|
||||
``-Wno-error=parentheses``.
|
||||
- Clang now better preserves the sugared types of pointers to member.
|
||||
- Clang now better preserves the presence of the template keyword with dependent
|
||||
prefixes.
|
||||
- When printing types for diagnostics, clang now doesn't suppress the scopes of
|
||||
template arguments contained within nested names.
|
||||
- The ``-Wshift-bool`` warning has been added to warn about shifting a boolean. (#GH28334)
|
||||
- Fixed diagnostics adding a trailing ``::`` when printing some source code
|
||||
constructs, like base classes.
|
||||
|
@ -1837,15 +1837,14 @@ public:
|
||||
TagDecl *OwnedTagDecl = nullptr) const;
|
||||
QualType getDependentNameType(ElaboratedTypeKeyword Keyword,
|
||||
NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name,
|
||||
QualType Canon = QualType()) const;
|
||||
const IdentifierInfo *Name) const;
|
||||
|
||||
QualType getDependentTemplateSpecializationType(
|
||||
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name, ArrayRef<TemplateArgumentLoc> Args) const;
|
||||
ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name,
|
||||
ArrayRef<TemplateArgumentLoc> Args) const;
|
||||
QualType getDependentTemplateSpecializationType(
|
||||
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args) const;
|
||||
ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name,
|
||||
ArrayRef<TemplateArgument> Args, bool IsCanonical = false) const;
|
||||
|
||||
TemplateArgument getInjectedTemplateArg(NamedDecl *ParamDecl) const;
|
||||
|
||||
@ -2393,11 +2392,9 @@ public:
|
||||
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
|
||||
bool TemplateKeyword,
|
||||
TemplateName Template) const;
|
||||
TemplateName
|
||||
getDependentTemplateName(const DependentTemplateStorage &Name) const;
|
||||
|
||||
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name) const;
|
||||
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
|
||||
OverloadedOperatorKind Operator) const;
|
||||
TemplateName
|
||||
getSubstTemplateTemplateParm(TemplateName replacement, Decl *AssociatedDecl,
|
||||
unsigned Index,
|
||||
|
@ -446,6 +446,14 @@ class TypeSourceInfo;
|
||||
/// returns nullptr only if the FromId was nullptr.
|
||||
IdentifierInfo *Import(const IdentifierInfo *FromId);
|
||||
|
||||
/// Import the given identifier or overloaded operator from the "from"
|
||||
/// context into the "to" context.
|
||||
///
|
||||
/// \returns The equivalent identifier or overloaded operator in the "to"
|
||||
/// context.
|
||||
IdentifierOrOverloadedOperator
|
||||
Import(IdentifierOrOverloadedOperator FromIO);
|
||||
|
||||
/// Import the given Objective-C selector from the "from"
|
||||
/// context into the "to" context.
|
||||
///
|
||||
|
@ -396,8 +396,7 @@ public:
|
||||
// FIXME: Provide a NestedNameSpecifier visitor.
|
||||
NestedNameSpecifier *Qualifier = T->getQualifier();
|
||||
if (NestedNameSpecifier::SpecifierKind K = Qualifier->getKind();
|
||||
K == NestedNameSpecifier::TypeSpec ||
|
||||
K == NestedNameSpecifier::TypeSpecWithTemplate)
|
||||
K == NestedNameSpecifier::TypeSpec)
|
||||
Visit(Qualifier->getAsType());
|
||||
if (T->isSugared())
|
||||
Visit(T->getMostRecentCXXRecordDecl()->getTypeForDecl());
|
||||
|
@ -279,10 +279,8 @@ public:
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
cur = NestedNameSpecifier::Create(ctx, cur,
|
||||
kind == NestedNameSpecifier::TypeSpecWithTemplate,
|
||||
asImpl().readQualType().getTypePtr());
|
||||
asImpl().readQualType().getTypePtr());
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::Global:
|
||||
|
@ -260,7 +260,6 @@ public:
|
||||
continue;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
asImpl().writeQualType(QualType(NNS->getAsType(), 0));
|
||||
continue;
|
||||
|
||||
|
@ -52,8 +52,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
|
||||
enum StoredSpecifierKind {
|
||||
StoredIdentifier = 0,
|
||||
StoredDecl = 1,
|
||||
StoredTypeSpec = 2,
|
||||
StoredTypeSpecWithTemplate = 3
|
||||
StoredTypeSpec = 2
|
||||
};
|
||||
|
||||
/// The nested name specifier that precedes this nested name
|
||||
@ -89,10 +88,6 @@ public:
|
||||
/// A type, stored as a Type*.
|
||||
TypeSpec,
|
||||
|
||||
/// A type that was preceded by the 'template' keyword,
|
||||
/// stored as a Type*.
|
||||
TypeSpecWithTemplate,
|
||||
|
||||
/// The global specifier '::'. There is no stored value.
|
||||
Global,
|
||||
|
||||
@ -137,9 +132,8 @@ public:
|
||||
const NamespaceAliasDecl *Alias);
|
||||
|
||||
/// Builds a nested name specifier that names a type.
|
||||
static NestedNameSpecifier *Create(const ASTContext &Context,
|
||||
NestedNameSpecifier *Prefix,
|
||||
bool Template, const Type *T);
|
||||
static NestedNameSpecifier *
|
||||
Create(const ASTContext &Context, NestedNameSpecifier *Prefix, const Type *T);
|
||||
|
||||
/// Builds a specifier that consists of just an identifier.
|
||||
///
|
||||
@ -194,8 +188,7 @@ public:
|
||||
|
||||
/// Retrieve the type stored in this nested name specifier.
|
||||
const Type *getAsType() const {
|
||||
if (Prefix.getInt() == StoredTypeSpec ||
|
||||
Prefix.getInt() == StoredTypeSpecWithTemplate)
|
||||
if (Prefix.getInt() == StoredTypeSpec)
|
||||
return (const Type *)Specifier;
|
||||
|
||||
return nullptr;
|
||||
@ -401,13 +394,10 @@ public:
|
||||
/// \param Context The AST context in which this nested-name-specifier
|
||||
/// resides.
|
||||
///
|
||||
/// \param TemplateKWLoc The location of the 'template' keyword, if present.
|
||||
///
|
||||
/// \param TL The TypeLoc that describes the type preceding the '::'.
|
||||
///
|
||||
/// \param ColonColonLoc The location of the trailing '::'.
|
||||
void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL,
|
||||
SourceLocation ColonColonLoc);
|
||||
void Extend(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc);
|
||||
|
||||
/// Extend the current nested-name-specifier by another
|
||||
/// nested-name-specifier component of the form 'identifier::'.
|
||||
|
@ -94,6 +94,7 @@ public:
|
||||
void AddStmt(const Stmt *S);
|
||||
void AddIdentifierInfo(const IdentifierInfo *II);
|
||||
void AddNestedNameSpecifier(const NestedNameSpecifier *NNS);
|
||||
void AddDependentTemplateName(const DependentTemplateStorage &Name);
|
||||
void AddTemplateName(TemplateName Name);
|
||||
void AddDeclarationName(DeclarationName Name, bool TreatAsDecl = false);
|
||||
void AddTemplateArgument(TemplateArgument TA);
|
||||
|
@ -692,25 +692,26 @@ let Class = PropertyTypeCase<TemplateName, "QualifiedTemplate"> in {
|
||||
let Class = PropertyTypeCase<TemplateName, "DependentTemplate"> in {
|
||||
def : ReadHelper<[{
|
||||
auto dtn = node.getAsDependentTemplateName();
|
||||
auto name = dtn->getName();
|
||||
}]>;
|
||||
def : Property<"qualifier", NestedNameSpecifier> {
|
||||
let Read = [{ dtn->getQualifier() }];
|
||||
}
|
||||
def : Property<"identifier", Optional<Identifier>> {
|
||||
let Read = [{ makeOptionalFromPointer(
|
||||
dtn->isIdentifier()
|
||||
? dtn->getIdentifier()
|
||||
: nullptr) }];
|
||||
let Read = [{ makeOptionalFromPointer(name.getIdentifier()) }];
|
||||
}
|
||||
def : Property<"operatorKind", OverloadedOperatorKind> {
|
||||
let Conditional = [{ !identifier }];
|
||||
let Read = [{ dtn->getOperator() }];
|
||||
let Read = [{ name.getOperator() }];
|
||||
}
|
||||
def : Property<"HasTemplateKeyword", Bool> {
|
||||
let Read = [{ dtn->hasTemplateKeyword() }];
|
||||
}
|
||||
def : Creator<[{
|
||||
if (identifier) {
|
||||
return ctx.getDependentTemplateName(qualifier, *identifier);
|
||||
return ctx.getDependentTemplateName({qualifier, *identifier, HasTemplateKeyword});
|
||||
} else {
|
||||
return ctx.getDependentTemplateName(qualifier, *operatorKind);
|
||||
return ctx.getDependentTemplateName({qualifier, *operatorKind, HasTemplateKeyword});
|
||||
}
|
||||
}]>;
|
||||
}
|
||||
|
@ -795,7 +795,6 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
|
||||
return true;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
TRY_TO(TraverseType(QualType(NNS->getAsType(), 0)));
|
||||
}
|
||||
|
||||
@ -820,7 +819,6 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc(
|
||||
return true;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
TRY_TO(TraverseTypeLoc(NNS.getTypeLoc()));
|
||||
break;
|
||||
}
|
||||
@ -1172,7 +1170,8 @@ DEF_TRAVERSE_TYPE(DependentNameType,
|
||||
{ TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); })
|
||||
|
||||
DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, {
|
||||
TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
|
||||
const DependentTemplateStorage &S = T->getDependentTemplateName();
|
||||
TRY_TO(TraverseNestedNameSpecifier(S.getQualifier()));
|
||||
TRY_TO(TraverseTemplateArguments(T->template_arguments()));
|
||||
})
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "clang/AST/DependenceFlags.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Basic/OperatorKinds.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
@ -537,6 +538,35 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct IdentifierOrOverloadedOperator {
|
||||
IdentifierOrOverloadedOperator() = default;
|
||||
IdentifierOrOverloadedOperator(const IdentifierInfo *II);
|
||||
IdentifierOrOverloadedOperator(OverloadedOperatorKind OOK);
|
||||
|
||||
/// Returns the identifier to which this template name refers.
|
||||
const IdentifierInfo *getIdentifier() const {
|
||||
if (getOperator() != OO_None)
|
||||
return nullptr;
|
||||
return reinterpret_cast<const IdentifierInfo *>(PtrOrOp);
|
||||
}
|
||||
|
||||
/// Return the overloaded operator to which this template name refers.
|
||||
OverloadedOperatorKind getOperator() const {
|
||||
uintptr_t OOK = -PtrOrOp;
|
||||
return OOK < NUM_OVERLOADED_OPERATORS ? OverloadedOperatorKind(OOK)
|
||||
: OO_None;
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const;
|
||||
|
||||
bool operator==(const IdentifierOrOverloadedOperator &Other) const {
|
||||
return PtrOrOp == Other.PtrOrOp;
|
||||
};
|
||||
|
||||
private:
|
||||
uintptr_t PtrOrOp = 0;
|
||||
};
|
||||
|
||||
/// Represents a dependent template name that cannot be
|
||||
/// resolved prior to template instantiation.
|
||||
///
|
||||
@ -545,104 +575,53 @@ public:
|
||||
/// DependentTemplateName can refer to "MetaFun::template apply",
|
||||
/// where "MetaFun::" is the nested name specifier and "apply" is the
|
||||
/// template name referenced. The "template" keyword is implied.
|
||||
class DependentTemplateName : public llvm::FoldingSetNode {
|
||||
friend class ASTContext;
|
||||
|
||||
class DependentTemplateStorage {
|
||||
/// The nested name specifier that qualifies the template
|
||||
/// name.
|
||||
///
|
||||
/// The bit stored in this qualifier describes whether the \c Name field
|
||||
/// is interpreted as an IdentifierInfo pointer (when clear) or as an
|
||||
/// overloaded operator kind (when set).
|
||||
/// was preceeded by a template keyword.
|
||||
llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier;
|
||||
|
||||
/// The dependent template name.
|
||||
union {
|
||||
/// The identifier template name.
|
||||
///
|
||||
/// Only valid when the bit on \c Qualifier is clear.
|
||||
const IdentifierInfo *Identifier;
|
||||
|
||||
/// The overloaded operator name.
|
||||
///
|
||||
/// Only valid when the bit on \c Qualifier is set.
|
||||
OverloadedOperatorKind Operator;
|
||||
};
|
||||
|
||||
/// The canonical template name to which this dependent
|
||||
/// template name refers.
|
||||
///
|
||||
/// The canonical template name for a dependent template name is
|
||||
/// another dependent template name whose nested name specifier is
|
||||
/// canonical.
|
||||
TemplateName CanonicalTemplateName;
|
||||
|
||||
DependentTemplateName(NestedNameSpecifier *Qualifier,
|
||||
const IdentifierInfo *Identifier)
|
||||
: Qualifier(Qualifier, false), Identifier(Identifier),
|
||||
CanonicalTemplateName(this) {}
|
||||
|
||||
DependentTemplateName(NestedNameSpecifier *Qualifier,
|
||||
const IdentifierInfo *Identifier,
|
||||
TemplateName Canon)
|
||||
: Qualifier(Qualifier, false), Identifier(Identifier),
|
||||
CanonicalTemplateName(Canon) {}
|
||||
|
||||
DependentTemplateName(NestedNameSpecifier *Qualifier,
|
||||
OverloadedOperatorKind Operator)
|
||||
: Qualifier(Qualifier, true), Operator(Operator),
|
||||
CanonicalTemplateName(this) {}
|
||||
|
||||
DependentTemplateName(NestedNameSpecifier *Qualifier,
|
||||
OverloadedOperatorKind Operator,
|
||||
TemplateName Canon)
|
||||
: Qualifier(Qualifier, true), Operator(Operator),
|
||||
CanonicalTemplateName(Canon) {}
|
||||
IdentifierOrOverloadedOperator Name;
|
||||
|
||||
public:
|
||||
DependentTemplateStorage(NestedNameSpecifier *Qualifier,
|
||||
IdentifierOrOverloadedOperator Name,
|
||||
bool HasTemplateKeyword);
|
||||
|
||||
/// Return the nested name specifier that qualifies this name.
|
||||
NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
|
||||
|
||||
/// Determine whether this template name refers to an identifier.
|
||||
bool isIdentifier() const { return !Qualifier.getInt(); }
|
||||
IdentifierOrOverloadedOperator getName() const { return Name; }
|
||||
|
||||
/// Returns the identifier to which this template name refers.
|
||||
const IdentifierInfo *getIdentifier() const {
|
||||
assert(isIdentifier() && "Template name isn't an identifier?");
|
||||
return Identifier;
|
||||
}
|
||||
/// Was this template name was preceeded by the template keyword?
|
||||
bool hasTemplateKeyword() const { return Qualifier.getInt(); }
|
||||
|
||||
/// Determine whether this template name refers to an overloaded
|
||||
/// operator.
|
||||
bool isOverloadedOperator() const { return Qualifier.getInt(); }
|
||||
TemplateNameDependence getDependence() const;
|
||||
|
||||
/// Return the overloaded operator to which this template name refers.
|
||||
OverloadedOperatorKind getOperator() const {
|
||||
assert(isOverloadedOperator() &&
|
||||
"Template name isn't an overloaded operator?");
|
||||
return Operator;
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
if (isIdentifier())
|
||||
Profile(ID, getQualifier(), getIdentifier());
|
||||
else
|
||||
Profile(ID, getQualifier(), getOperator());
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
Profile(ID, getQualifier(), getName(), hasTemplateKeyword());
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Identifier) {
|
||||
IdentifierOrOverloadedOperator Name,
|
||||
bool HasTemplateKeyword) {
|
||||
ID.AddPointer(NNS);
|
||||
ID.AddBoolean(false);
|
||||
ID.AddPointer(Identifier);
|
||||
ID.AddBoolean(HasTemplateKeyword);
|
||||
Name.Profile(ID);
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
|
||||
OverloadedOperatorKind Operator) {
|
||||
ID.AddPointer(NNS);
|
||||
ID.AddBoolean(true);
|
||||
ID.AddInteger(Operator);
|
||||
}
|
||||
void print(raw_ostream &OS, const PrintingPolicy &Policy) const;
|
||||
};
|
||||
|
||||
class DependentTemplateName : public DependentTemplateStorage,
|
||||
public llvm::FoldingSetNode {
|
||||
friend class ASTContext;
|
||||
using DependentTemplateStorage::DependentTemplateStorage;
|
||||
DependentTemplateName(const DependentTemplateStorage &S)
|
||||
: DependentTemplateStorage(S) {}
|
||||
};
|
||||
|
||||
} // namespace clang.
|
||||
|
@ -7098,21 +7098,17 @@ class DependentTemplateSpecializationType : public TypeWithKeyword,
|
||||
public llvm::FoldingSetNode {
|
||||
friend class ASTContext; // ASTContext creates these
|
||||
|
||||
/// The nested name specifier containing the qualifier.
|
||||
NestedNameSpecifier *NNS;
|
||||
|
||||
/// The identifier of the template.
|
||||
const IdentifierInfo *Name;
|
||||
DependentTemplateStorage Name;
|
||||
|
||||
DependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword,
|
||||
NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name,
|
||||
const DependentTemplateStorage &Name,
|
||||
ArrayRef<TemplateArgument> Args,
|
||||
QualType Canon);
|
||||
|
||||
public:
|
||||
NestedNameSpecifier *getQualifier() const { return NNS; }
|
||||
const IdentifierInfo *getIdentifier() const { return Name; }
|
||||
const DependentTemplateStorage &getDependentTemplateName() const {
|
||||
return Name;
|
||||
}
|
||||
|
||||
ArrayRef<TemplateArgument> template_arguments() const {
|
||||
return {reinterpret_cast<const TemplateArgument *>(this + 1),
|
||||
@ -7123,14 +7119,12 @@ public:
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
|
||||
Profile(ID, Context, getKeyword(), NNS, Name, template_arguments());
|
||||
Profile(ID, Context, getKeyword(), Name, template_arguments());
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||
const ASTContext &Context,
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
|
||||
ElaboratedTypeKeyword Keyword,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
const IdentifierInfo *Name,
|
||||
const DependentTemplateStorage &Name,
|
||||
ArrayRef<TemplateArgument> Args);
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
|
@ -2502,8 +2502,9 @@ public:
|
||||
if (!getLocalData()->QualifierData)
|
||||
return NestedNameSpecifierLoc();
|
||||
|
||||
return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
|
||||
getLocalData()->QualifierData);
|
||||
return NestedNameSpecifierLoc(
|
||||
getTypePtr()->getDependentTemplateName().getQualifier(),
|
||||
getLocalData()->QualifierData);
|
||||
}
|
||||
|
||||
void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
|
||||
@ -2516,8 +2517,8 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
assert(QualifierLoc.getNestedNameSpecifier()
|
||||
== getTypePtr()->getQualifier() &&
|
||||
assert(QualifierLoc.getNestedNameSpecifier() ==
|
||||
getTypePtr()->getDependentTemplateName().getQualifier() &&
|
||||
"Inconsistent nested-name-specifier pointer");
|
||||
getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
|
||||
}
|
||||
|
@ -774,22 +774,37 @@ let Class = TemplateSpecializationType in {
|
||||
}
|
||||
|
||||
let Class = DependentTemplateSpecializationType in {
|
||||
def : ReadHelper<[{
|
||||
const auto &dtn = node->getDependentTemplateName();
|
||||
auto name = dtn.getName();
|
||||
}]>;
|
||||
|
||||
def : Property<"qualifier", NestedNameSpecifier> {
|
||||
let Read = [{ dtn.getQualifier() }];
|
||||
}
|
||||
def : Property<"identifier", Optional<Identifier>> {
|
||||
let Read = [{ makeOptionalFromPointer(name.getIdentifier()) }];
|
||||
}
|
||||
def : Property<"operatorKind", OverloadedOperatorKind> {
|
||||
let Conditional = [{ !identifier }];
|
||||
let Read = [{ name.getOperator() }];
|
||||
}
|
||||
def : Property<"HasTemplateKeyword", Bool> {
|
||||
let Read = [{ dtn.hasTemplateKeyword() }];
|
||||
}
|
||||
|
||||
def : Property<"keyword", ElaboratedTypeKeyword> {
|
||||
let Read = [{ node->getKeyword() }];
|
||||
}
|
||||
def : Property<"qualifier", NestedNameSpecifier> {
|
||||
let Read = [{ node->getQualifier() }];
|
||||
}
|
||||
def : Property<"name", Identifier> {
|
||||
let Read = [{ node->getIdentifier() }];
|
||||
}
|
||||
def : Property<"templateArguments", Array<TemplateArgument>> {
|
||||
let Read = [{ node->template_arguments() }];
|
||||
}
|
||||
|
||||
def : Creator<[{
|
||||
return ctx.getDependentTemplateSpecializationType(keyword, qualifier,
|
||||
name, templateArguments);
|
||||
DependentTemplateStorage S(qualifier, identifier ? IdentifierOrOverloadedOperator(*identifier) :
|
||||
IdentifierOrOverloadedOperator(*operatorKind),
|
||||
HasTemplateKeyword);
|
||||
return ctx.getDependentTemplateSpecializationType(keyword, S, templateArguments);
|
||||
}]>;
|
||||
}
|
||||
|
||||
@ -926,22 +941,10 @@ let Class = DependentNameType in {
|
||||
def : Property<"qualifier", NestedNameSpecifier> {
|
||||
let Read = [{ node->getQualifier() }];
|
||||
}
|
||||
def : Property<"name", Identifier> {
|
||||
let Read = [{ node->getIdentifier() }];
|
||||
}
|
||||
def : Property<"underlyingType", Optional<QualType>> {
|
||||
let Read = [{
|
||||
node->isCanonicalUnqualified()
|
||||
? std::nullopt
|
||||
: std::optional<QualType>(node->getCanonicalTypeInternal())
|
||||
}];
|
||||
}
|
||||
def : Property<"name", Identifier> { let Read = [{ node->getIdentifier() }]; }
|
||||
|
||||
def : Creator<[{
|
||||
QualType canon = (underlyingType
|
||||
? ctx.getCanonicalType(*underlyingType)
|
||||
: QualType());
|
||||
return ctx.getDependentNameType(keyword, qualifier, name, canon);
|
||||
return ctx.getDependentNameType(keyword, qualifier, name);
|
||||
}]>;
|
||||
}
|
||||
|
||||
|
@ -107,8 +107,7 @@ public:
|
||||
/// \param TL The TypeLoc that describes the type preceding the '::'.
|
||||
///
|
||||
/// \param ColonColonLoc The location of the trailing '::'.
|
||||
void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL,
|
||||
SourceLocation ColonColonLoc);
|
||||
void Extend(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc);
|
||||
|
||||
/// Extend the current nested-name-specifier by another
|
||||
/// nested-name-specifier component of the form 'identifier::'.
|
||||
|
@ -4033,7 +4033,6 @@ QualType ASTContext::getMemberPointerType(QualType T,
|
||||
if (!Qualifier) {
|
||||
assert(Cls && "At least one of Qualifier or Cls must be provided");
|
||||
Qualifier = NestedNameSpecifier::Create(*this, /*Prefix=*/nullptr,
|
||||
/*Template=*/false,
|
||||
getTypeDeclType(Cls).getTypePtr());
|
||||
} else if (!Cls) {
|
||||
Cls = Qualifier->getAsRecordDecl();
|
||||
@ -4052,8 +4051,7 @@ QualType ASTContext::getMemberPointerType(QualType T,
|
||||
if (!Cls)
|
||||
return getCanonicalNestedNameSpecifier(Qualifier);
|
||||
NestedNameSpecifier *R = NestedNameSpecifier::Create(
|
||||
*this, /*Prefix=*/nullptr, /*Template=*/false,
|
||||
Cls->getCanonicalDecl()->getTypeForDecl());
|
||||
*this, /*Prefix=*/nullptr, Cls->getCanonicalDecl()->getTypeForDecl());
|
||||
assert(R == getCanonicalNestedNameSpecifier(R));
|
||||
return R;
|
||||
}();
|
||||
@ -5739,24 +5737,26 @@ ASTContext::getMacroQualifiedType(QualType UnderlyingTy,
|
||||
|
||||
QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
|
||||
NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name,
|
||||
QualType Canon) const {
|
||||
if (Canon.isNull()) {
|
||||
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
|
||||
if (CanonNNS != NNS)
|
||||
Canon = getDependentNameType(Keyword, CanonNNS, Name);
|
||||
}
|
||||
|
||||
const IdentifierInfo *Name) const {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
DependentNameType::Profile(ID, Keyword, NNS, Name);
|
||||
|
||||
void *InsertPos = nullptr;
|
||||
DependentNameType *T
|
||||
= DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
if (T)
|
||||
if (DependentNameType *T =
|
||||
DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(T, 0);
|
||||
|
||||
T = new (*this, alignof(DependentNameType))
|
||||
QualType Canon;
|
||||
if (NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
|
||||
CanonNNS != NNS) {
|
||||
Canon = getDependentNameType(Keyword, CanonNNS, Name);
|
||||
[[maybe_unused]] DependentNameType *T =
|
||||
DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
assert(!T && "broken canonicalization");
|
||||
assert(Canon.isCanonical());
|
||||
}
|
||||
|
||||
DependentNameType *T = new (*this, alignof(DependentNameType))
|
||||
DependentNameType(Keyword, NNS, Name, Canon);
|
||||
Types.push_back(T);
|
||||
DependentNameTypes.InsertNode(T, InsertPos);
|
||||
@ -5764,61 +5764,63 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword,
|
||||
}
|
||||
|
||||
QualType ASTContext::getDependentTemplateSpecializationType(
|
||||
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name, ArrayRef<TemplateArgumentLoc> Args) const {
|
||||
ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name,
|
||||
ArrayRef<TemplateArgumentLoc> Args) const {
|
||||
// TODO: avoid this copy
|
||||
SmallVector<TemplateArgument, 16> ArgCopy;
|
||||
for (unsigned I = 0, E = Args.size(); I != E; ++I)
|
||||
ArgCopy.push_back(Args[I].getArgument());
|
||||
return getDependentTemplateSpecializationType(Keyword, NNS, Name, ArgCopy);
|
||||
return getDependentTemplateSpecializationType(Keyword, Name, ArgCopy);
|
||||
}
|
||||
|
||||
QualType
|
||||
ASTContext::getDependentTemplateSpecializationType(
|
||||
ElaboratedTypeKeyword Keyword,
|
||||
NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name,
|
||||
ArrayRef<TemplateArgument> Args) const {
|
||||
assert((!NNS || NNS->isDependent()) &&
|
||||
"nested-name-specifier must be dependent");
|
||||
|
||||
QualType ASTContext::getDependentTemplateSpecializationType(
|
||||
ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name,
|
||||
ArrayRef<TemplateArgument> Args, bool IsCanonical) const {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
DependentTemplateSpecializationType::Profile(ID, *this, Keyword, NNS,
|
||||
Name, Args);
|
||||
DependentTemplateSpecializationType::Profile(ID, *this, Keyword, Name, Args);
|
||||
|
||||
void *InsertPos = nullptr;
|
||||
DependentTemplateSpecializationType *T
|
||||
= DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
if (T)
|
||||
if (auto *T = DependentTemplateSpecializationTypes.FindNodeOrInsertPos(
|
||||
ID, InsertPos))
|
||||
return QualType(T, 0);
|
||||
|
||||
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
|
||||
|
||||
ElaboratedTypeKeyword CanonKeyword = Keyword;
|
||||
if (Keyword == ElaboratedTypeKeyword::None)
|
||||
CanonKeyword = ElaboratedTypeKeyword::Typename;
|
||||
|
||||
bool AnyNonCanonArgs = false;
|
||||
auto CanonArgs =
|
||||
::getCanonicalTemplateArguments(*this, Args, AnyNonCanonArgs);
|
||||
NestedNameSpecifier *NNS = Name.getQualifier();
|
||||
|
||||
QualType Canon;
|
||||
if (AnyNonCanonArgs || CanonNNS != NNS || CanonKeyword != Keyword) {
|
||||
Canon = getDependentTemplateSpecializationType(CanonKeyword, CanonNNS,
|
||||
Name,
|
||||
CanonArgs);
|
||||
if (!IsCanonical) {
|
||||
ElaboratedTypeKeyword CanonKeyword = Keyword != ElaboratedTypeKeyword::None
|
||||
? Keyword
|
||||
: ElaboratedTypeKeyword::Typename;
|
||||
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
|
||||
bool AnyNonCanonArgs = false;
|
||||
auto CanonArgs =
|
||||
::getCanonicalTemplateArguments(*this, Args, AnyNonCanonArgs);
|
||||
|
||||
// Find the insert position again.
|
||||
[[maybe_unused]] auto *Nothing =
|
||||
DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
assert(!Nothing && "canonical type broken");
|
||||
if (AnyNonCanonArgs || CanonNNS != NNS || !Name.hasTemplateKeyword() ||
|
||||
CanonKeyword != Keyword) {
|
||||
Canon = getDependentTemplateSpecializationType(
|
||||
CanonKeyword, {CanonNNS, Name.getName(), /*HasTemplateKeyword=*/true},
|
||||
CanonArgs, /*IsCanonical=*/true);
|
||||
// Find the insert position again.
|
||||
[[maybe_unused]] auto *Nothing =
|
||||
DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID,
|
||||
InsertPos);
|
||||
assert(!Nothing && "canonical type broken");
|
||||
}
|
||||
} else {
|
||||
assert(Keyword != ElaboratedTypeKeyword::None);
|
||||
assert(Name.hasTemplateKeyword());
|
||||
assert(NNS == getCanonicalNestedNameSpecifier(NNS));
|
||||
#ifndef NDEBUG
|
||||
for (const auto &Arg : Args)
|
||||
assert(Arg.structurallyEquals(getCanonicalTemplateArgument(Arg)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void *Mem = Allocate((sizeof(DependentTemplateSpecializationType) +
|
||||
sizeof(TemplateArgument) * Args.size()),
|
||||
alignof(DependentTemplateSpecializationType));
|
||||
T = new (Mem) DependentTemplateSpecializationType(Keyword, NNS,
|
||||
Name, Args, Canon);
|
||||
auto *T =
|
||||
new (Mem) DependentTemplateSpecializationType(Keyword, Name, Args, Canon);
|
||||
Types.push_back(T);
|
||||
DependentTemplateSpecializationTypes.InsertNode(T, InsertPos);
|
||||
return QualType(T, 0);
|
||||
@ -6916,12 +6918,13 @@ ASTContext::getNameForTemplate(TemplateName Name,
|
||||
|
||||
case TemplateName::DependentTemplate: {
|
||||
DependentTemplateName *DTN = Name.getAsDependentTemplateName();
|
||||
IdentifierOrOverloadedOperator TN = DTN->getName();
|
||||
DeclarationName DName;
|
||||
if (DTN->isIdentifier()) {
|
||||
DName = DeclarationNames.getIdentifier(DTN->getIdentifier());
|
||||
if (const IdentifierInfo *II = TN.getIdentifier()) {
|
||||
DName = DeclarationNames.getIdentifier(II);
|
||||
return DeclarationNameInfo(DName, NameLoc);
|
||||
} else {
|
||||
DName = DeclarationNames.getCXXOperatorName(DTN->getOperator());
|
||||
DName = DeclarationNames.getCXXOperatorName(TN.getOperator());
|
||||
// DNInfo work in progress: FIXME: source locations?
|
||||
DeclarationNameLoc DNLoc =
|
||||
DeclarationNameLoc::makeCXXOperatorNameLoc(SourceRange());
|
||||
@ -6996,7 +6999,13 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name,
|
||||
case TemplateName::DependentTemplate: {
|
||||
DependentTemplateName *DTN = Name.getAsDependentTemplateName();
|
||||
assert(DTN && "Non-dependent template names must refer to template decls.");
|
||||
return DTN->CanonicalTemplateName;
|
||||
NestedNameSpecifier *Qualifier = DTN->getQualifier();
|
||||
NestedNameSpecifier *CanonQualifier =
|
||||
getCanonicalNestedNameSpecifier(Qualifier);
|
||||
if (Qualifier != CanonQualifier || !DTN->hasTemplateKeyword())
|
||||
return getDependentTemplateName({CanonQualifier, DTN->getName(),
|
||||
/*HasTemplateKeyword=*/true});
|
||||
return Name;
|
||||
}
|
||||
|
||||
case TemplateName::SubstTemplateTemplateParmPack: {
|
||||
@ -7229,7 +7238,6 @@ static bool isSameQualifier(const NestedNameSpecifier *X,
|
||||
// We've already checked that we named the same namespace.
|
||||
break;
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
if (X->getAsType()->getCanonicalTypeInternal() !=
|
||||
Y->getAsType()->getCanonicalTypeInternal())
|
||||
return false;
|
||||
@ -7608,8 +7616,7 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
|
||||
|
||||
// The difference between TypeSpec and TypeSpecWithTemplate is that the
|
||||
// latter will have the 'template' keyword when printed.
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate: {
|
||||
case NestedNameSpecifier::TypeSpec: {
|
||||
const Type *T = getCanonicalType(NNS->getAsType());
|
||||
|
||||
// If we have some kind of dependent-named type (e.g., "typename T::type"),
|
||||
@ -7622,11 +7629,19 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
|
||||
if (const auto *DNT = T->getAs<DependentNameType>())
|
||||
return NestedNameSpecifier::Create(*this, DNT->getQualifier(),
|
||||
DNT->getIdentifier());
|
||||
if (const auto *DTST = T->getAs<DependentTemplateSpecializationType>())
|
||||
return NestedNameSpecifier::Create(*this, DTST->getQualifier(), true, T);
|
||||
|
||||
// TODO: Set 'Template' parameter to true for other template types.
|
||||
return NestedNameSpecifier::Create(*this, nullptr, false, T);
|
||||
if (const auto *DTST = T->getAs<DependentTemplateSpecializationType>()) {
|
||||
const DependentTemplateStorage &DTN = DTST->getDependentTemplateName();
|
||||
QualType NewT = getDependentTemplateSpecializationType(
|
||||
ElaboratedTypeKeyword::Typename,
|
||||
{/*NNS=*/nullptr, DTN.getName(), /*HasTemplateKeyword=*/true},
|
||||
DTST->template_arguments(), /*IsCanonical=*/true);
|
||||
assert(NewT.isCanonical());
|
||||
NestedNameSpecifier *Prefix = DTN.getQualifier();
|
||||
if (!Prefix)
|
||||
Prefix = getCanonicalNestedNameSpecifier(NNS->getPrefix());
|
||||
return NestedNameSpecifier::Create(*this, Prefix, NewT.getTypePtr());
|
||||
}
|
||||
return NestedNameSpecifier::Create(*this, nullptr, T);
|
||||
}
|
||||
|
||||
case NestedNameSpecifier::Global:
|
||||
@ -10056,75 +10071,20 @@ TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
|
||||
return TemplateName(QTN);
|
||||
}
|
||||
|
||||
/// Retrieve the template name that represents a dependent
|
||||
/// template name such as \c MetaFun::template apply.
|
||||
TemplateName
|
||||
ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name) const {
|
||||
assert((!NNS || NNS->isDependent()) &&
|
||||
"Nested name specifier must be dependent");
|
||||
|
||||
llvm::FoldingSetNodeID ID;
|
||||
DependentTemplateName::Profile(ID, NNS, Name);
|
||||
|
||||
void *InsertPos = nullptr;
|
||||
DependentTemplateName *QTN =
|
||||
DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
|
||||
|
||||
if (QTN)
|
||||
return TemplateName(QTN);
|
||||
|
||||
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
|
||||
if (CanonNNS == NNS) {
|
||||
QTN = new (*this, alignof(DependentTemplateName))
|
||||
DependentTemplateName(NNS, Name);
|
||||
} else {
|
||||
TemplateName Canon = getDependentTemplateName(CanonNNS, Name);
|
||||
QTN = new (*this, alignof(DependentTemplateName))
|
||||
DependentTemplateName(NNS, Name, Canon);
|
||||
DependentTemplateName *CheckQTN =
|
||||
DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
|
||||
assert(!CheckQTN && "Dependent type name canonicalization broken");
|
||||
(void)CheckQTN;
|
||||
}
|
||||
|
||||
DependentTemplateNames.InsertNode(QTN, InsertPos);
|
||||
return TemplateName(QTN);
|
||||
}
|
||||
|
||||
/// Retrieve the template name that represents a dependent
|
||||
/// template name such as \c MetaFun::template operator+.
|
||||
TemplateName
|
||||
ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
|
||||
OverloadedOperatorKind Operator) const {
|
||||
assert((!NNS || NNS->isDependent()) &&
|
||||
"Nested name specifier must be dependent");
|
||||
|
||||
ASTContext::getDependentTemplateName(const DependentTemplateStorage &S) const {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
DependentTemplateName::Profile(ID, NNS, Operator);
|
||||
S.Profile(ID);
|
||||
|
||||
void *InsertPos = nullptr;
|
||||
DependentTemplateName *QTN
|
||||
= DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
|
||||
|
||||
if (QTN)
|
||||
if (DependentTemplateName *QTN =
|
||||
DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return TemplateName(QTN);
|
||||
|
||||
NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
|
||||
if (CanonNNS == NNS) {
|
||||
QTN = new (*this, alignof(DependentTemplateName))
|
||||
DependentTemplateName(NNS, Operator);
|
||||
} else {
|
||||
TemplateName Canon = getDependentTemplateName(CanonNNS, Operator);
|
||||
QTN = new (*this, alignof(DependentTemplateName))
|
||||
DependentTemplateName(NNS, Operator, Canon);
|
||||
|
||||
DependentTemplateName *CheckQTN
|
||||
= DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
|
||||
assert(!CheckQTN && "Dependent template name canonicalization broken");
|
||||
(void)CheckQTN;
|
||||
}
|
||||
|
||||
DependentTemplateName *QTN =
|
||||
new (*this, alignof(DependentTemplateName)) DependentTemplateName(S);
|
||||
DependentTemplateNames.InsertNode(QTN, InsertPos);
|
||||
return TemplateName(QTN);
|
||||
}
|
||||
@ -13543,19 +13503,12 @@ static NestedNameSpecifier *getCommonNNS(ASTContext &Ctx,
|
||||
R = NestedNameSpecifier::Create(Ctx, P, ::getCommonDeclChecked(N1, N2));
|
||||
break;
|
||||
}
|
||||
case NestedNameSpecifier::SpecifierKind::TypeSpec:
|
||||
case NestedNameSpecifier::SpecifierKind::TypeSpecWithTemplate: {
|
||||
case NestedNameSpecifier::SpecifierKind::TypeSpec: {
|
||||
// FIXME: See comment below, on Super case.
|
||||
if (K2 == NestedNameSpecifier::SpecifierKind::Super)
|
||||
return Ctx.getCanonicalNestedNameSpecifier(NNS1);
|
||||
|
||||
assert(K2 == NestedNameSpecifier::SpecifierKind::TypeSpec ||
|
||||
K2 == NestedNameSpecifier::SpecifierKind::TypeSpecWithTemplate);
|
||||
|
||||
// Only keep the template keyword if both sides have it.
|
||||
bool Template =
|
||||
K1 == NestedNameSpecifier::SpecifierKind::TypeSpecWithTemplate &&
|
||||
K2 == NestedNameSpecifier::SpecifierKind::TypeSpecWithTemplate;
|
||||
assert(K2 == NestedNameSpecifier::SpecifierKind::TypeSpec);
|
||||
|
||||
const Type *T1 = NNS1->getAsType(), *T2 = NNS2->getAsType();
|
||||
if (T1 == T2) {
|
||||
@ -13569,13 +13522,12 @@ static NestedNameSpecifier *getCommonNNS(ASTContext &Ctx,
|
||||
bool IsSame = isa<DependentTemplateSpecializationType>(T1);
|
||||
NestedNameSpecifier *P =
|
||||
::getCommonNNS(Ctx, NNS1->getPrefix(), NNS2->getPrefix(), IsSame);
|
||||
R = NestedNameSpecifier::Create(Ctx, P, Template, T1);
|
||||
R = NestedNameSpecifier::Create(Ctx, P, T1);
|
||||
break;
|
||||
}
|
||||
// TODO: Try to salvage the original prefix.
|
||||
// If getCommonSugaredType removed any top level sugar, the original prefix
|
||||
// is not applicable anymore.
|
||||
NestedNameSpecifier *P = nullptr;
|
||||
const Type *T = Ctx.getCommonSugaredType(QualType(T1, 0), QualType(T2, 0),
|
||||
/*Unqualified=*/true)
|
||||
.getTypePtr();
|
||||
@ -13585,7 +13537,7 @@ static NestedNameSpecifier *getCommonNNS(ASTContext &Ctx,
|
||||
case Type::Elaborated: {
|
||||
// An ElaboratedType is stripped off, it's Qualifier becomes the prefix.
|
||||
auto *ET = cast<ElaboratedType>(T);
|
||||
R = NestedNameSpecifier::Create(Ctx, ET->getQualifier(), Template,
|
||||
R = NestedNameSpecifier::Create(Ctx, ET->getQualifier(),
|
||||
ET->getNamedType().getTypePtr());
|
||||
break;
|
||||
}
|
||||
@ -13600,16 +13552,17 @@ static NestedNameSpecifier *getCommonNNS(ASTContext &Ctx,
|
||||
// A DependentTemplateSpecializationType loses it's Qualifier, which
|
||||
// is turned into the prefix.
|
||||
auto *DTST = cast<DependentTemplateSpecializationType>(T);
|
||||
T = Ctx.getDependentTemplateSpecializationType(
|
||||
DTST->getKeyword(), /*NNS=*/nullptr, DTST->getIdentifier(),
|
||||
DTST->template_arguments())
|
||||
const DependentTemplateStorage &DTN = DTST->getDependentTemplateName();
|
||||
DependentTemplateStorage NewDTN(/*Qualifier=*/nullptr, DTN.getName(),
|
||||
DTN.hasTemplateKeyword());
|
||||
T = Ctx.getDependentTemplateSpecializationType(DTST->getKeyword(), NewDTN,
|
||||
DTST->template_arguments())
|
||||
.getTypePtr();
|
||||
P = DTST->getQualifier();
|
||||
R = NestedNameSpecifier::Create(Ctx, DTST->getQualifier(), Template, T);
|
||||
R = NestedNameSpecifier::Create(Ctx, DTN.getQualifier(), T);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
R = NestedNameSpecifier::Create(Ctx, P, Template, T);
|
||||
R = NestedNameSpecifier::Create(Ctx, /*Prefix=*/nullptr, T);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -14052,19 +14005,22 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X,
|
||||
assert(NX->getIdentifier() == NY->getIdentifier());
|
||||
return Ctx.getDependentNameType(
|
||||
getCommonTypeKeyword(NX, NY),
|
||||
getCommonQualifier(Ctx, NX, NY, /*IsSame=*/true), NX->getIdentifier(),
|
||||
NX->getCanonicalTypeInternal());
|
||||
getCommonQualifier(Ctx, NX, NY, /*IsSame=*/true), NX->getIdentifier());
|
||||
}
|
||||
case Type::DependentTemplateSpecialization: {
|
||||
const auto *TX = cast<DependentTemplateSpecializationType>(X),
|
||||
*TY = cast<DependentTemplateSpecializationType>(Y);
|
||||
assert(TX->getIdentifier() == TY->getIdentifier());
|
||||
auto As = getCommonTemplateArguments(Ctx, TX->template_arguments(),
|
||||
TY->template_arguments());
|
||||
const DependentTemplateStorage &SX = TX->getDependentTemplateName(),
|
||||
&SY = TY->getDependentTemplateName();
|
||||
assert(SX.getName() == SY.getName());
|
||||
DependentTemplateStorage Name(
|
||||
getCommonNNS(Ctx, SX.getQualifier(), SY.getQualifier(),
|
||||
/*IsSame=*/true),
|
||||
SX.getName(), SX.hasTemplateKeyword() || SY.hasTemplateKeyword());
|
||||
return Ctx.getDependentTemplateSpecializationType(
|
||||
getCommonTypeKeyword(TX, TY),
|
||||
getCommonQualifier(Ctx, TX, TY, /*IsSame=*/true), TX->getIdentifier(),
|
||||
As);
|
||||
getCommonTypeKeyword(TX, TY), Name, As);
|
||||
}
|
||||
case Type::UnaryTransform: {
|
||||
const auto *TX = cast<UnaryTransformType>(X),
|
||||
|
@ -1707,11 +1707,10 @@ ASTNodeImporter::VisitPackExpansionType(const PackExpansionType *T) {
|
||||
|
||||
ExpectedType ASTNodeImporter::VisitDependentTemplateSpecializationType(
|
||||
const DependentTemplateSpecializationType *T) {
|
||||
auto ToQualifierOrErr = import(T->getQualifier());
|
||||
if (!ToQualifierOrErr)
|
||||
return ToQualifierOrErr.takeError();
|
||||
|
||||
IdentifierInfo *ToName = Importer.Import(T->getIdentifier());
|
||||
const DependentTemplateStorage &DTN = T->getDependentTemplateName();
|
||||
auto QualifierOrErr = import(DTN.getQualifier());
|
||||
if (!QualifierOrErr)
|
||||
return QualifierOrErr.takeError();
|
||||
|
||||
SmallVector<TemplateArgument, 2> ToPack;
|
||||
ToPack.reserve(T->template_arguments().size());
|
||||
@ -1719,7 +1718,10 @@ ExpectedType ASTNodeImporter::VisitDependentTemplateSpecializationType(
|
||||
return std::move(Err);
|
||||
|
||||
return Importer.getToContext().getDependentTemplateSpecializationType(
|
||||
T->getKeyword(), *ToQualifierOrErr, ToName, ToPack);
|
||||
T->getKeyword(),
|
||||
{*QualifierOrErr, Importer.Import(DTN.getName()),
|
||||
DTN.hasTemplateKeyword()},
|
||||
ToPack);
|
||||
}
|
||||
|
||||
ExpectedType
|
||||
@ -1729,18 +1731,8 @@ ASTNodeImporter::VisitDependentNameType(const DependentNameType *T) {
|
||||
return ToQualifierOrErr.takeError();
|
||||
|
||||
IdentifierInfo *Name = Importer.Import(T->getIdentifier());
|
||||
|
||||
QualType Canon;
|
||||
if (T != T->getCanonicalTypeInternal().getTypePtr()) {
|
||||
if (ExpectedType TyOrErr = import(T->getCanonicalTypeInternal()))
|
||||
Canon = (*TyOrErr).getCanonicalType();
|
||||
else
|
||||
return TyOrErr.takeError();
|
||||
}
|
||||
|
||||
return Importer.getToContext().getDependentNameType(T->getKeyword(),
|
||||
*ToQualifierOrErr,
|
||||
Name, Canon);
|
||||
*ToQualifierOrErr, Name);
|
||||
}
|
||||
|
||||
ExpectedType
|
||||
@ -9788,12 +9780,8 @@ ASTImporter::Import(NestedNameSpecifier *FromNNS) {
|
||||
return RDOrErr.takeError();
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
if (ExpectedTypePtr TyOrErr = Import(FromNNS->getAsType())) {
|
||||
bool TSTemplate =
|
||||
FromNNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate;
|
||||
return NestedNameSpecifier::Create(ToContext, Prefix, TSTemplate,
|
||||
*TyOrErr);
|
||||
return NestedNameSpecifier::Create(ToContext, Prefix, *TyOrErr);
|
||||
} else {
|
||||
return TyOrErr.takeError();
|
||||
}
|
||||
@ -9851,21 +9839,13 @@ ASTImporter::Import(NestedNameSpecifierLoc FromNNS) {
|
||||
ToLocalBeginLoc, ToLocalEndLoc);
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate: {
|
||||
case NestedNameSpecifier::TypeSpec: {
|
||||
SourceLocation ToTLoc;
|
||||
if (Error Err = importInto(ToTLoc, NNS.getTypeLoc().getBeginLoc()))
|
||||
return std::move(Err);
|
||||
TypeSourceInfo *TSI = getToContext().getTrivialTypeSourceInfo(
|
||||
QualType(Spec->getAsType(), 0), ToTLoc);
|
||||
if (Kind == NestedNameSpecifier::TypeSpecWithTemplate)
|
||||
// ToLocalBeginLoc is here the location of the 'template' keyword.
|
||||
Builder.Extend(getToContext(), ToLocalBeginLoc, TSI->getTypeLoc(),
|
||||
ToLocalEndLoc);
|
||||
else
|
||||
// No location for 'template' keyword here.
|
||||
Builder.Extend(getToContext(), SourceLocation{}, TSI->getTypeLoc(),
|
||||
ToLocalEndLoc);
|
||||
QualType(Spec->getAsType(), 0), ToTLoc);
|
||||
Builder.Extend(getToContext(), TSI->getTypeLoc(), ToLocalEndLoc);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -9934,14 +9914,8 @@ Expected<TemplateName> ASTImporter::Import(TemplateName From) {
|
||||
auto QualifierOrErr = Import(DTN->getQualifier());
|
||||
if (!QualifierOrErr)
|
||||
return QualifierOrErr.takeError();
|
||||
|
||||
if (DTN->isIdentifier()) {
|
||||
return ToContext.getDependentTemplateName(*QualifierOrErr,
|
||||
Import(DTN->getIdentifier()));
|
||||
}
|
||||
|
||||
return ToContext.getDependentTemplateName(*QualifierOrErr,
|
||||
DTN->getOperator());
|
||||
return ToContext.getDependentTemplateName(
|
||||
{*QualifierOrErr, Import(DTN->getName()), DTN->hasTemplateKeyword()});
|
||||
}
|
||||
|
||||
case TemplateName::SubstTemplateTemplateParm: {
|
||||
@ -10312,6 +10286,13 @@ IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) {
|
||||
return ToId;
|
||||
}
|
||||
|
||||
IdentifierOrOverloadedOperator
|
||||
ASTImporter::Import(IdentifierOrOverloadedOperator FromIO) {
|
||||
if (const IdentifierInfo *FromII = FromIO.getIdentifier())
|
||||
return Import(FromII);
|
||||
return FromIO.getOperator();
|
||||
}
|
||||
|
||||
Expected<Selector> ASTImporter::Import(Selector FromSel) {
|
||||
if (FromSel.isNull())
|
||||
return Selector{};
|
||||
|
@ -566,7 +566,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
||||
return IsStructurallyEquivalent(Context, NNS1->getAsNamespaceAlias(),
|
||||
NNS2->getAsNamespaceAlias());
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
return IsStructurallyEquivalent(Context, QualType(NNS1->getAsType(), 0),
|
||||
QualType(NNS2->getAsType(), 0));
|
||||
case NestedNameSpecifier::Global:
|
||||
@ -578,6 +577,19 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
||||
const DependentTemplateStorage &S1,
|
||||
const DependentTemplateStorage &S2) {
|
||||
if (!IsStructurallyEquivalent(Context, S1.getQualifier(), S2.getQualifier()))
|
||||
return false;
|
||||
|
||||
IdentifierOrOverloadedOperator IO1 = S1.getName(), IO2 = S2.getName();
|
||||
const IdentifierInfo *II1 = IO1.getIdentifier(), *II2 = IO2.getIdentifier();
|
||||
if (!II1 || !II2)
|
||||
return IO1.getOperator() == IO2.getOperator();
|
||||
return IsStructurallyEquivalent(II1, II2);
|
||||
}
|
||||
|
||||
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
||||
const TemplateName &N1,
|
||||
const TemplateName &N2) {
|
||||
@ -614,19 +626,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
||||
return TN1->getDeclName() == TN2->getDeclName();
|
||||
}
|
||||
|
||||
case TemplateName::DependentTemplate: {
|
||||
DependentTemplateName *DN1 = N1.getAsDependentTemplateName(),
|
||||
*DN2 = N2.getAsDependentTemplateName();
|
||||
if (!IsStructurallyEquivalent(Context, DN1->getQualifier(),
|
||||
DN2->getQualifier()))
|
||||
return false;
|
||||
if (DN1->isIdentifier() && DN2->isIdentifier())
|
||||
return IsStructurallyEquivalent(DN1->getIdentifier(),
|
||||
DN2->getIdentifier());
|
||||
else if (DN1->isOverloadedOperator() && DN2->isOverloadedOperator())
|
||||
return DN1->getOperator() == DN2->getOperator();
|
||||
return false;
|
||||
}
|
||||
case TemplateName::DependentTemplate:
|
||||
return IsStructurallyEquivalent(Context, *N1.getAsDependentTemplateName(),
|
||||
*N2.getAsDependentTemplateName());
|
||||
|
||||
case TemplateName::SubstTemplateTemplateParmPack: {
|
||||
SubstTemplateTemplateParmPackStorage
|
||||
@ -1315,11 +1317,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
||||
case Type::DependentTemplateSpecialization: {
|
||||
const auto *Spec1 = cast<DependentTemplateSpecializationType>(T1);
|
||||
const auto *Spec2 = cast<DependentTemplateSpecializationType>(T2);
|
||||
if (!IsStructurallyEquivalent(Context, Spec1->getQualifier(),
|
||||
Spec2->getQualifier()))
|
||||
if (Spec1->getKeyword() != Spec2->getKeyword())
|
||||
return false;
|
||||
if (!IsStructurallyEquivalent(Spec1->getIdentifier(),
|
||||
Spec2->getIdentifier()))
|
||||
if (!IsStructurallyEquivalent(Context, Spec1->getDependentTemplateName(),
|
||||
Spec2->getDependentTemplateName()))
|
||||
return false;
|
||||
if (!IsStructurallyEquivalent(Context, Spec1->template_arguments(),
|
||||
Spec2->template_arguments()))
|
||||
|
@ -1327,7 +1327,7 @@ void CXXNameMangler::manglePrefix(QualType type) {
|
||||
type->getAs<DependentTemplateSpecializationType>()) {
|
||||
if (!mangleSubstitution(QualType(DTST, 0))) {
|
||||
TemplateName Template = getASTContext().getDependentTemplateName(
|
||||
DTST->getQualifier(), DTST->getIdentifier());
|
||||
DTST->getDependentTemplateName());
|
||||
mangleTemplatePrefix(Template);
|
||||
|
||||
// FIXME: GCC does not appear to mangle the template arguments when
|
||||
@ -1395,8 +1395,7 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
|
||||
mangleSourceNameWithAbiTags(qualifier->getAsNamespaceAlias());
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate: {
|
||||
case NestedNameSpecifier::TypeSpec: {
|
||||
const Type *type = qualifier->getAsType();
|
||||
|
||||
// We only want to use an unresolved-type encoding if this is one of:
|
||||
@ -2181,7 +2180,17 @@ void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {
|
||||
return;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
if (NestedNameSpecifier *Prefix = qualifier->getPrefix()) {
|
||||
const auto *DTST =
|
||||
cast<DependentTemplateSpecializationType>(qualifier->getAsType());
|
||||
QualType NewT = getASTContext().getDependentTemplateSpecializationType(
|
||||
DTST->getKeyword(),
|
||||
{Prefix, DTST->getDependentTemplateName().getName(),
|
||||
/*HasTemplateKeyword=*/true},
|
||||
DTST->template_arguments(), /*IsCanonical=*/true);
|
||||
manglePrefix(NewT);
|
||||
return;
|
||||
}
|
||||
manglePrefix(QualType(qualifier->getAsType(), 0));
|
||||
return;
|
||||
|
||||
@ -2265,10 +2274,11 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
|
||||
if (Clang11Compat && mangleSubstitution(Template))
|
||||
return;
|
||||
|
||||
if (const IdentifierInfo *Id = Dependent->getIdentifier())
|
||||
if (IdentifierOrOverloadedOperator Name = Dependent->getName();
|
||||
const IdentifierInfo *Id = Name.getIdentifier())
|
||||
mangleSourceName(Id);
|
||||
else
|
||||
mangleOperatorName(Dependent->getOperator(), UnknownArity);
|
||||
mangleOperatorName(Name.getOperator(), UnknownArity);
|
||||
|
||||
addSubstitution(Template);
|
||||
}
|
||||
@ -2376,12 +2386,13 @@ void CXXNameMangler::mangleType(TemplateName TN) {
|
||||
|
||||
case TemplateName::DependentTemplate: {
|
||||
const DependentTemplateName *Dependent = TN.getAsDependentTemplateName();
|
||||
assert(Dependent->isIdentifier());
|
||||
const IdentifierInfo *II = Dependent->getName().getIdentifier();
|
||||
assert(II);
|
||||
|
||||
// <class-enum-type> ::= <name>
|
||||
// <name> ::= <nested-name>
|
||||
mangleUnresolvedPrefix(Dependent->getQualifier());
|
||||
mangleSourceName(Dependent->getIdentifier());
|
||||
mangleSourceName(II);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2572,8 +2583,8 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
|
||||
const DependentTemplateSpecializationType *DTST =
|
||||
cast<DependentTemplateSpecializationType>(Ty);
|
||||
TemplateName Template = getASTContext().getDependentTemplateName(
|
||||
DTST->getQualifier(), DTST->getIdentifier());
|
||||
mangleSourceName(DTST->getIdentifier());
|
||||
DTST->getDependentTemplateName());
|
||||
mangleTemplatePrefix(Template);
|
||||
mangleTemplateArgs(Template, DTST->template_arguments());
|
||||
break;
|
||||
}
|
||||
@ -4481,10 +4492,8 @@ void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) {
|
||||
// Dependently-scoped template types are nested if they have a prefix.
|
||||
Out << 'N';
|
||||
|
||||
// TODO: avoid making this TemplateName.
|
||||
TemplateName Prefix =
|
||||
getASTContext().getDependentTemplateName(T->getQualifier(),
|
||||
T->getIdentifier());
|
||||
getASTContext().getDependentTemplateName(T->getDependentTemplateName());
|
||||
mangleTemplatePrefix(Prefix);
|
||||
|
||||
// FIXME: GCC does not appear to mangle the template arguments when
|
||||
|
@ -98,14 +98,13 @@ NestedNameSpecifier::Create(const ASTContext &Context,
|
||||
return FindOrInsert(Context, Mockup);
|
||||
}
|
||||
|
||||
NestedNameSpecifier *
|
||||
NestedNameSpecifier::Create(const ASTContext &Context,
|
||||
NestedNameSpecifier *Prefix,
|
||||
bool Template, const Type *T) {
|
||||
NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
|
||||
NestedNameSpecifier *Prefix,
|
||||
const Type *T) {
|
||||
assert(T && "Type cannot be NULL");
|
||||
NestedNameSpecifier Mockup;
|
||||
Mockup.Prefix.setPointer(Prefix);
|
||||
Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec);
|
||||
Mockup.Prefix.setInt(StoredTypeSpec);
|
||||
Mockup.Specifier = const_cast<Type*>(T);
|
||||
return FindOrInsert(Context, Mockup);
|
||||
}
|
||||
@ -155,9 +154,6 @@ NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
|
||||
|
||||
case StoredTypeSpec:
|
||||
return TypeSpec;
|
||||
|
||||
case StoredTypeSpecWithTemplate:
|
||||
return TypeSpecWithTemplate;
|
||||
}
|
||||
|
||||
llvm_unreachable("Invalid NNS Kind!");
|
||||
@ -189,7 +185,6 @@ CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
|
||||
return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier));
|
||||
|
||||
case StoredTypeSpec:
|
||||
case StoredTypeSpecWithTemplate:
|
||||
return getAsType()->getAsCXXRecordDecl();
|
||||
}
|
||||
|
||||
@ -222,9 +217,13 @@ NestedNameSpecifierDependence NestedNameSpecifier::getDependence() const {
|
||||
return NestedNameSpecifierDependence::None;
|
||||
}
|
||||
|
||||
case TypeSpec:
|
||||
case TypeSpecWithTemplate:
|
||||
return toNestedNameSpecifierDependendence(getAsType()->getDependence());
|
||||
case TypeSpec: {
|
||||
NestedNameSpecifierDependence Dep =
|
||||
toNestedNameSpecifierDependendence(getAsType()->getDependence());
|
||||
if (NestedNameSpecifier *Prefix = getPrefix())
|
||||
Dep |= Prefix->getDependence();
|
||||
return Dep;
|
||||
}
|
||||
}
|
||||
llvm_unreachable("Invalid NNS Kind!");
|
||||
}
|
||||
@ -254,17 +253,17 @@ NestedNameSpecifier::translateToType(const ASTContext &Context) const {
|
||||
.getDependentNameType(ElaboratedTypeKeyword::None, Prefix,
|
||||
getAsIdentifier())
|
||||
.getTypePtr();
|
||||
case SpecifierKind::TypeSpec:
|
||||
case SpecifierKind::TypeSpecWithTemplate: {
|
||||
case SpecifierKind::TypeSpec: {
|
||||
const Type *T = getAsType();
|
||||
switch (T->getTypeClass()) {
|
||||
case Type::DependentTemplateSpecialization: {
|
||||
const auto *DT = cast<DependentTemplateSpecializationType>(T);
|
||||
// FIXME: The type node can't represent the template keyword.
|
||||
const DependentTemplateStorage &DTN = DT->getDependentTemplateName();
|
||||
return Context
|
||||
.getDependentTemplateSpecializationType(ElaboratedTypeKeyword::None,
|
||||
Prefix, DT->getIdentifier(),
|
||||
DT->template_arguments())
|
||||
.getDependentTemplateSpecializationType(
|
||||
ElaboratedTypeKeyword::None,
|
||||
{Prefix, DTN.getName(), DTN.hasTemplateKeyword()},
|
||||
DT->template_arguments())
|
||||
.getTypePtr();
|
||||
}
|
||||
case Type::Record:
|
||||
@ -324,59 +323,11 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
|
||||
OS << "__super";
|
||||
break;
|
||||
|
||||
case TypeSpecWithTemplate:
|
||||
OS << "template ";
|
||||
// Fall through to print the type.
|
||||
[[fallthrough]];
|
||||
|
||||
case TypeSpec: {
|
||||
const auto *Record =
|
||||
dyn_cast_or_null<ClassTemplateSpecializationDecl>(getAsRecordDecl());
|
||||
if (ResolveTemplateArguments && Record) {
|
||||
// Print the type trait with resolved template parameters.
|
||||
Record->printName(OS, Policy);
|
||||
printTemplateArgumentList(
|
||||
OS, Record->getTemplateArgs().asArray(), Policy,
|
||||
Record->getSpecializedTemplate()->getTemplateParameters());
|
||||
break;
|
||||
}
|
||||
const Type *T = getAsType();
|
||||
|
||||
PrintingPolicy InnerPolicy(Policy);
|
||||
InnerPolicy.SuppressScope = true;
|
||||
InnerPolicy.SuppressTagKeyword = true;
|
||||
|
||||
// Nested-name-specifiers are intended to contain minimally-qualified
|
||||
// types. An actual ElaboratedType will not occur, since we'll store
|
||||
// just the type that is referred to in the nested-name-specifier (e.g.,
|
||||
// a TypedefType, TagType, etc.). However, when we are dealing with
|
||||
// dependent template-id types (e.g., Outer<T>::template Inner<U>),
|
||||
// the type requires its own nested-name-specifier for uniqueness, so we
|
||||
// suppress that nested-name-specifier during printing.
|
||||
assert(!isa<ElaboratedType>(T) &&
|
||||
"Elaborated type in nested-name-specifier");
|
||||
if (const TemplateSpecializationType *SpecType
|
||||
= dyn_cast<TemplateSpecializationType>(T)) {
|
||||
// Print the template name without its corresponding
|
||||
// nested-name-specifier.
|
||||
SpecType->getTemplateName().print(OS, InnerPolicy,
|
||||
TemplateName::Qualified::None);
|
||||
|
||||
// Print the template argument list.
|
||||
printTemplateArgumentList(OS, SpecType->template_arguments(),
|
||||
InnerPolicy);
|
||||
} else if (const auto *DepSpecType =
|
||||
dyn_cast<DependentTemplateSpecializationType>(T)) {
|
||||
// Print the template name without its corresponding
|
||||
// nested-name-specifier.
|
||||
OS << DepSpecType->getIdentifier()->getName();
|
||||
// Print the template argument list.
|
||||
printTemplateArgumentList(OS, DepSpecType->template_arguments(),
|
||||
InnerPolicy);
|
||||
} else {
|
||||
// Print the type normally
|
||||
QualType(T, 0).print(OS, InnerPolicy);
|
||||
}
|
||||
QualType(getAsType(), 0).print(OS, InnerPolicy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -421,7 +372,6 @@ NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
|
||||
Length += sizeof(SourceLocation::UIntTy);
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
// The "void*" that points at the TypeLoc data.
|
||||
// Note: the 'template' keyword is part of the TypeLoc.
|
||||
@ -485,7 +435,6 @@ SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
|
||||
LoadSourceLocation(Data, Offset),
|
||||
LoadSourceLocation(Data, Offset + sizeof(SourceLocation::UIntTy)));
|
||||
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
case NestedNameSpecifier::TypeSpec: {
|
||||
// The "void*" that points at the TypeLoc data.
|
||||
// Note: the 'template' keyword is part of the TypeLoc.
|
||||
@ -500,8 +449,7 @@ SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
|
||||
}
|
||||
|
||||
TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
|
||||
if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec &&
|
||||
Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate)
|
||||
if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec)
|
||||
return TypeLoc();
|
||||
|
||||
// The "void*" that points at the TypeLoc data.
|
||||
@ -609,13 +557,10 @@ operator=(const NestedNameSpecifierLocBuilder &Other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
|
||||
SourceLocation TemplateKWLoc,
|
||||
TypeLoc TL,
|
||||
void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, TypeLoc TL,
|
||||
SourceLocation ColonColonLoc) {
|
||||
Representation = NestedNameSpecifier::Create(Context, Representation,
|
||||
TemplateKWLoc.isValid(),
|
||||
TL.getTypePtr());
|
||||
Representation =
|
||||
NestedNameSpecifier::Create(Context, Representation, TL.getTypePtr());
|
||||
|
||||
// Push source-location info into the buffer.
|
||||
SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
|
||||
@ -697,8 +642,7 @@ void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
|
||||
SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate: {
|
||||
case NestedNameSpecifier::TypeSpec: {
|
||||
TypeSourceInfo *TSInfo
|
||||
= Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
|
||||
R.getBegin());
|
||||
|
@ -128,7 +128,6 @@ void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
|
||||
AddDecl(NNS->getAsNamespaceAlias());
|
||||
break;
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
AddType(NNS->getAsType());
|
||||
break;
|
||||
case NestedNameSpecifier::Global:
|
||||
@ -137,6 +136,16 @@ void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
|
||||
}
|
||||
}
|
||||
|
||||
void ODRHash::AddDependentTemplateName(const DependentTemplateStorage &Name) {
|
||||
if (NestedNameSpecifier *NNS = Name.getQualifier())
|
||||
AddNestedNameSpecifier(NNS);
|
||||
if (IdentifierOrOverloadedOperator IO = Name.getName();
|
||||
const IdentifierInfo *II = IO.getIdentifier())
|
||||
AddIdentifierInfo(II);
|
||||
else
|
||||
ID.AddInteger(IO.getOperator());
|
||||
}
|
||||
|
||||
void ODRHash::AddTemplateName(TemplateName Name) {
|
||||
auto Kind = Name.getKind();
|
||||
ID.AddInteger(Kind);
|
||||
@ -153,10 +162,13 @@ void ODRHash::AddTemplateName(TemplateName Name) {
|
||||
AddTemplateName(QTN->getUnderlyingTemplate());
|
||||
break;
|
||||
}
|
||||
case TemplateName::DependentTemplate: {
|
||||
AddDependentTemplateName(*Name.getAsDependentTemplateName());
|
||||
break;
|
||||
}
|
||||
// TODO: Support these cases.
|
||||
case TemplateName::OverloadedTemplate:
|
||||
case TemplateName::AssumedTemplate:
|
||||
case TemplateName::DependentTemplate:
|
||||
case TemplateName::SubstTemplateTemplateParm:
|
||||
case TemplateName::SubstTemplateTemplateParmPack:
|
||||
case TemplateName::UsingTemplate:
|
||||
@ -1221,8 +1233,7 @@ public:
|
||||
|
||||
void VisitDependentTemplateSpecializationType(
|
||||
const DependentTemplateSpecializationType *T) {
|
||||
AddIdentifierInfo(T->getIdentifier());
|
||||
AddNestedNameSpecifier(T->getQualifier());
|
||||
Hash.AddDependentTemplateName(T->getDependentTemplateName());
|
||||
ID.AddInteger(T->template_arguments().size());
|
||||
for (const auto &TA : T->template_arguments()) {
|
||||
Hash.AddTemplateArgument(TA);
|
||||
|
@ -212,6 +212,7 @@ static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
|
||||
bool WithGlobalNsPrefix) {
|
||||
switch (Scope->getKind()) {
|
||||
case NestedNameSpecifier::Global:
|
||||
case NestedNameSpecifier::Super:
|
||||
// Already fully qualified
|
||||
return Scope;
|
||||
case NestedNameSpecifier::Namespace:
|
||||
@ -232,9 +233,7 @@ static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier(
|
||||
// but use the name of it's prefix.
|
||||
return getFullyQualifiedNestedNameSpecifier(
|
||||
Ctx, Scope->getPrefix(), WithGlobalNsPrefix);
|
||||
case NestedNameSpecifier::Super:
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate: {
|
||||
case NestedNameSpecifier::TypeSpec: {
|
||||
const Type *Type = Scope->getAsType();
|
||||
// Find decl context.
|
||||
const TagDecl *TD = nullptr;
|
||||
@ -366,8 +365,7 @@ NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx,
|
||||
}
|
||||
|
||||
return NestedNameSpecifier::Create(
|
||||
Ctx, createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix),
|
||||
false /*No TemplateKeyword*/, TypePtr);
|
||||
Ctx, createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix), TypePtr);
|
||||
}
|
||||
|
||||
/// Return the fully qualified type, including fully-qualified
|
||||
|
@ -122,6 +122,31 @@ void SubstTemplateTemplateParmPackStorage::Profile(
|
||||
ID.AddBoolean(Final);
|
||||
}
|
||||
|
||||
IdentifierOrOverloadedOperator::IdentifierOrOverloadedOperator(
|
||||
const IdentifierInfo *II)
|
||||
: PtrOrOp(reinterpret_cast<uintptr_t>(II)) {
|
||||
static_assert(NUM_OVERLOADED_OPERATORS <= 4096,
|
||||
"NUM_OVERLOADED_OPERATORS is too large");
|
||||
assert(II);
|
||||
assert(getIdentifier() == II);
|
||||
}
|
||||
IdentifierOrOverloadedOperator::IdentifierOrOverloadedOperator(
|
||||
OverloadedOperatorKind OOK)
|
||||
: PtrOrOp(-uintptr_t(OOK)) {
|
||||
assert(OOK != OO_None);
|
||||
assert(getOperator() == OOK);
|
||||
}
|
||||
|
||||
void IdentifierOrOverloadedOperator::Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
if (auto *Identifier = getIdentifier()) {
|
||||
ID.AddBoolean(false);
|
||||
ID.AddPointer(Identifier);
|
||||
} else {
|
||||
ID.AddBoolean(true);
|
||||
ID.AddInteger(getOperator());
|
||||
}
|
||||
}
|
||||
|
||||
TemplateName::TemplateName(void *Ptr) {
|
||||
Storage = StorageType::getFromOpaqueValue(Ptr);
|
||||
}
|
||||
@ -275,6 +300,36 @@ UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DependentTemplateStorage::DependentTemplateStorage(
|
||||
NestedNameSpecifier *Qualifier, IdentifierOrOverloadedOperator Name,
|
||||
bool HasTemplateKeyword)
|
||||
: Qualifier(Qualifier, HasTemplateKeyword), Name(Name) {
|
||||
assert((!Qualifier || Qualifier->isDependent()) &&
|
||||
"Qualifier must be dependent");
|
||||
}
|
||||
|
||||
TemplateNameDependence DependentTemplateStorage::getDependence() const {
|
||||
auto D = TemplateNameDependence::DependentInstantiation;
|
||||
if (NestedNameSpecifier *Qualifier = getQualifier())
|
||||
D |= toTemplateNameDependence(Qualifier->getDependence());
|
||||
return D;
|
||||
}
|
||||
|
||||
void DependentTemplateStorage::print(raw_ostream &OS,
|
||||
const PrintingPolicy &Policy) const {
|
||||
if (NestedNameSpecifier *NNS = getQualifier())
|
||||
NNS->print(OS, Policy);
|
||||
|
||||
if (hasTemplateKeyword())
|
||||
OS << "template ";
|
||||
|
||||
IdentifierOrOverloadedOperator Name = getName();
|
||||
if (const IdentifierInfo *II = Name.getIdentifier())
|
||||
OS << II->getName();
|
||||
else
|
||||
OS << "operator " << getOperatorSpelling(Name.getOperator());
|
||||
}
|
||||
|
||||
DeducedTemplateStorage *TemplateName::getAsDeducedTemplateName() const {
|
||||
if (UncommonTemplateNameStorage *Uncommon =
|
||||
dyn_cast_if_present<UncommonTemplateNameStorage *>(Storage))
|
||||
@ -313,7 +368,8 @@ TemplateNameDependence TemplateName::getDependence() const {
|
||||
case NameKind::DependentTemplate: {
|
||||
DependentTemplateName *S = getAsDependentTemplateName();
|
||||
auto D = TemplateNameDependence::DependentInstantiation;
|
||||
D |= toTemplateNameDependence(S->getQualifier()->getDependence());
|
||||
if (NestedNameSpecifier *Qualifier = S->getQualifier())
|
||||
D |= toTemplateNameDependence(Qualifier->getDependence());
|
||||
return D;
|
||||
}
|
||||
case NameKind::SubstTemplateTemplateParm: {
|
||||
@ -401,14 +457,7 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
|
||||
else
|
||||
OS << *UTD;
|
||||
} else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
|
||||
if (NestedNameSpecifier *NNS = DTN->getQualifier())
|
||||
NNS->print(OS, Policy);
|
||||
OS << "template ";
|
||||
|
||||
if (DTN->isIdentifier())
|
||||
OS << DTN->getIdentifier()->getName();
|
||||
else
|
||||
OS << "operator " << getOperatorSpelling(DTN->getOperator());
|
||||
DTN->print(OS, Policy);
|
||||
} else if (SubstTemplateTemplateParmStorage *subst =
|
||||
getAsSubstTemplateTemplateParm()) {
|
||||
subst->getReplacement().print(OS, Policy, Qual);
|
||||
|
@ -1027,10 +1027,6 @@ void clang::TextNodeDumper::dumpNestedNameSpecifier(const NestedNameSpecifier *N
|
||||
OS << " TypeSpec";
|
||||
dumpType(QualType(NNS->getAsType(), 0));
|
||||
break;
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
OS << " TypeSpecWithTemplate";
|
||||
dumpType(QualType(NNS->getAsType(), 0));
|
||||
break;
|
||||
case NestedNameSpecifier::Global:
|
||||
OS << " Global";
|
||||
break;
|
||||
|
@ -3270,16 +3270,13 @@ StringRef TypeWithKeyword::getKeywordName(ElaboratedTypeKeyword Keyword) {
|
||||
}
|
||||
|
||||
DependentTemplateSpecializationType::DependentTemplateSpecializationType(
|
||||
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
|
||||
const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args, QualType Canon)
|
||||
ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name,
|
||||
ArrayRef<TemplateArgument> Args, QualType Canon)
|
||||
: TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon,
|
||||
TypeDependence::DependentInstantiation |
|
||||
(NNS ? toTypeDependence(NNS->getDependence())
|
||||
: TypeDependence::None)),
|
||||
NNS(NNS), Name(Name) {
|
||||
|
||||
toTypeDependence(Name.getDependence())),
|
||||
Name(Name) {
|
||||
DependentTemplateSpecializationTypeBits.NumArgs = Args.size();
|
||||
assert((!NNS || NNS->isDependent()) &&
|
||||
"DependentTemplateSpecializatonType requires dependent qualifier");
|
||||
auto *ArgBuffer = const_cast<TemplateArgument *>(template_arguments().data());
|
||||
for (const TemplateArgument &Arg : Args) {
|
||||
addDependence(toTypeDependence(Arg.getDependence() &
|
||||
@ -3289,16 +3286,12 @@ DependentTemplateSpecializationType::DependentTemplateSpecializationType(
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DependentTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
|
||||
const ASTContext &Context,
|
||||
ElaboratedTypeKeyword Keyword,
|
||||
NestedNameSpecifier *Qualifier,
|
||||
const IdentifierInfo *Name,
|
||||
ArrayRef<TemplateArgument> Args) {
|
||||
void DependentTemplateSpecializationType::Profile(
|
||||
llvm::FoldingSetNodeID &ID, const ASTContext &Context,
|
||||
ElaboratedTypeKeyword Keyword, const DependentTemplateStorage &Name,
|
||||
ArrayRef<TemplateArgument> Args) {
|
||||
ID.AddInteger(llvm::to_underlying(Keyword));
|
||||
ID.AddPointer(Qualifier);
|
||||
ID.AddPointer(Name);
|
||||
Name.Profile(ID);
|
||||
for (const TemplateArgument &Arg : Args)
|
||||
Arg.Profile(ID, Context);
|
||||
}
|
||||
|
@ -569,9 +569,10 @@ void
|
||||
DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
|
||||
SourceLocation Loc) {
|
||||
setElaboratedKeywordLoc(Loc);
|
||||
if (getTypePtr()->getQualifier()) {
|
||||
if (NestedNameSpecifier *Qualifier =
|
||||
getTypePtr()->getDependentTemplateName().getQualifier()) {
|
||||
NestedNameSpecifierLocBuilder Builder;
|
||||
Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
|
||||
Builder.MakeTrivial(Context, Qualifier, Loc);
|
||||
setQualifierLoc(Builder.getWithLocInContext(Context));
|
||||
} else {
|
||||
setQualifierLoc(NestedNameSpecifierLoc());
|
||||
|
@ -1793,9 +1793,7 @@ void TypePrinter::printDependentTemplateSpecializationBefore(
|
||||
if (T->getKeyword() != ElaboratedTypeKeyword::None)
|
||||
OS << " ";
|
||||
|
||||
if (T->getQualifier())
|
||||
T->getQualifier()->print(OS, Policy);
|
||||
OS << "template " << T->getIdentifier()->getName();
|
||||
T->getDependentTemplateName().print(OS, Policy);
|
||||
printTemplateArgumentList(OS, T->template_arguments(), Policy);
|
||||
spaceBeforePlaceHolder(OS);
|
||||
}
|
||||
@ -2498,14 +2496,18 @@ void clang::printTemplateArgumentList(raw_ostream &OS,
|
||||
ArrayRef<TemplateArgument> Args,
|
||||
const PrintingPolicy &Policy,
|
||||
const TemplateParameterList *TPL) {
|
||||
printTo(OS, Args, Policy, TPL, /*isPack*/ false, /*parmIndex*/ 0);
|
||||
PrintingPolicy InnerPolicy = Policy;
|
||||
InnerPolicy.SuppressScope = false;
|
||||
printTo(OS, Args, InnerPolicy, TPL, /*isPack*/ false, /*parmIndex*/ 0);
|
||||
}
|
||||
|
||||
void clang::printTemplateArgumentList(raw_ostream &OS,
|
||||
ArrayRef<TemplateArgumentLoc> Args,
|
||||
const PrintingPolicy &Policy,
|
||||
const TemplateParameterList *TPL) {
|
||||
printTo(OS, Args, Policy, TPL, /*isPack*/ false, /*parmIndex*/ 0);
|
||||
PrintingPolicy InnerPolicy = Policy;
|
||||
InnerPolicy.SuppressScope = false;
|
||||
printTo(OS, Args, InnerPolicy, TPL, /*isPack*/ false, /*parmIndex*/ 0);
|
||||
}
|
||||
|
||||
std::string Qualifiers::getAsString() const {
|
||||
|
@ -249,13 +249,6 @@ DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS,
|
||||
Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword);
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
// A type prefixed by the `template` keyword.
|
||||
Fragments.append("template", DeclarationFragments::FragmentKind::Keyword);
|
||||
Fragments.appendSpace();
|
||||
// Fallthrough after adding the keyword to handle the actual type.
|
||||
[[fallthrough]];
|
||||
|
||||
case NestedNameSpecifier::TypeSpec: {
|
||||
const Type *T = NNS->getAsType();
|
||||
// FIXME: Handle C++ template specialization type
|
||||
|
@ -277,7 +277,6 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
indexTypeLoc(NNS.getTypeLoc(), Parent, DC);
|
||||
break;
|
||||
}
|
||||
|
@ -587,12 +587,12 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
|
||||
<< II.getName()
|
||||
<< FixItHint::CreateInsertion(Tok.getLocation(), "template ");
|
||||
}
|
||||
|
||||
SourceLocation TemplateNameLoc = ConsumeToken();
|
||||
ConsumeToken();
|
||||
|
||||
TemplateNameKind TNK = Actions.ActOnTemplateName(
|
||||
getCurScope(), SS, TemplateNameLoc, TemplateName, ObjectType,
|
||||
EnteringContext, Template, /*AllowInjectedClassName*/ true);
|
||||
getCurScope(), SS, /*TemplateKWLoc=*/SourceLocation(), TemplateName,
|
||||
ObjectType, EnteringContext, Template,
|
||||
/*AllowInjectedClassName=*/true);
|
||||
if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),
|
||||
TemplateName, false))
|
||||
return true;
|
||||
|
@ -48,9 +48,9 @@ void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
|
||||
EndLocation = TemplateId->RAngleLoc;
|
||||
}
|
||||
|
||||
void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc,
|
||||
TypeLoc TL, SourceLocation ColonColonLoc) {
|
||||
Builder.Extend(Context, TemplateKWLoc, TL, ColonColonLoc);
|
||||
void CXXScopeSpec::Extend(ASTContext &Context, TypeLoc TL,
|
||||
SourceLocation ColonColonLoc) {
|
||||
Builder.Extend(Context, TL, ColonColonLoc);
|
||||
if (Range.getBegin().isInvalid())
|
||||
Range.setBegin(TL.getBeginLoc());
|
||||
Range.setEnd(ColonColonLoc);
|
||||
|
@ -365,9 +365,10 @@ HeuristicResolverImpl::resolveDependentNameType(const DependentNameType *DNT) {
|
||||
std::vector<const NamedDecl *>
|
||||
HeuristicResolverImpl::resolveTemplateSpecializationType(
|
||||
const DependentTemplateSpecializationType *DTST) {
|
||||
const DependentTemplateStorage &DTN = DTST->getDependentTemplateName();
|
||||
return resolveDependentMember(
|
||||
resolveNestedNameSpecifierToType(DTST->getQualifier()),
|
||||
DTST->getIdentifier(), TemplateFilter);
|
||||
resolveNestedNameSpecifierToType(DTN.getQualifier()),
|
||||
DTN.getName().getIdentifier(), TemplateFilter);
|
||||
}
|
||||
|
||||
std::vector<const NamedDecl *>
|
||||
@ -409,7 +410,6 @@ QualType HeuristicResolverImpl::resolveNestedNameSpecifierToType(
|
||||
// the TypeSpec cases too.
|
||||
switch (NNS->getKind()) {
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
return QualType(NNS->getAsType(), 0);
|
||||
case NestedNameSpecifier::Identifier: {
|
||||
return resolveDeclsToType(
|
||||
|
@ -145,8 +145,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
|
||||
case NestedNameSpecifier::NamespaceAlias:
|
||||
return NNS->getAsNamespaceAlias()->getNamespace();
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate: {
|
||||
case NestedNameSpecifier::TypeSpec: {
|
||||
const TagType *Tag = NNS->getAsType()->getAs<TagType>();
|
||||
assert(Tag && "Non-tag type in nested-name-specifier");
|
||||
return Tag->getDecl();
|
||||
@ -687,8 +686,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
|
||||
llvm_unreachable("Unhandled TypeDecl node in nested-name-specifier");
|
||||
}
|
||||
|
||||
SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T),
|
||||
IdInfo.CCLoc);
|
||||
SS.Extend(Context, TLB.getTypeLocInContext(Context, T), IdInfo.CCLoc);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -735,8 +733,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
|
||||
QualType T = Context.getTypeDeclType(ContainingClass);
|
||||
TypeLocBuilder TLB;
|
||||
TLB.pushTrivial(Context, T, IdInfo.IdentifierLoc);
|
||||
SS.Extend(Context, /*TemplateKWLoc=*/SourceLocation(),
|
||||
TLB.getTypeLocInContext(Context, T), IdInfo.IdentifierLoc);
|
||||
SS.Extend(Context, TLB.getTypeLocInContext(Context, T),
|
||||
IdInfo.IdentifierLoc);
|
||||
// Add the identifier to form a dependent name.
|
||||
SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc,
|
||||
IdInfo.CCLoc);
|
||||
@ -804,8 +802,7 @@ bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
|
||||
DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T);
|
||||
DecltypeTL.setDecltypeLoc(DS.getTypeSpecTypeLoc());
|
||||
DecltypeTL.setRParenLoc(DS.getTypeofParensRange().getEnd());
|
||||
SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T),
|
||||
ColonColonLoc);
|
||||
SS.Extend(Context, TLB.getTypeLocInContext(Context, T), ColonColonLoc);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -827,8 +824,7 @@ bool Sema::ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS,
|
||||
DS.getBeginLoc());
|
||||
PackIndexingTypeLoc PIT = TLB.push<PackIndexingTypeLoc>(Type);
|
||||
PIT.setEllipsisLoc(DS.getEllipsisLoc());
|
||||
SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, Type),
|
||||
ColonColonLoc);
|
||||
SS.Extend(Context, TLB.getTypeLocInContext(Context, Type), ColonColonLoc);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -862,12 +858,14 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
|
||||
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
|
||||
|
||||
DependentTemplateName *DTN = Template.getAsDependentTemplateName();
|
||||
if (DTN && DTN->isIdentifier()) {
|
||||
if (DTN && DTN->getName().getIdentifier()) {
|
||||
// Handle a dependent template specialization for which we cannot resolve
|
||||
// the template name.
|
||||
assert(DTN->getQualifier() == SS.getScopeRep());
|
||||
QualType T = Context.getDependentTemplateSpecializationType(
|
||||
ElaboratedTypeKeyword::None, DTN->getQualifier(), DTN->getIdentifier(),
|
||||
ElaboratedTypeKeyword::None,
|
||||
{/*Qualifier=*/nullptr, DTN->getName().getIdentifier(),
|
||||
TemplateKWLoc.isValid()},
|
||||
TemplateArgs.arguments());
|
||||
|
||||
// Create source-location information for this type.
|
||||
@ -875,7 +873,6 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
|
||||
DependentTemplateSpecializationTypeLoc SpecTL
|
||||
= Builder.push<DependentTemplateSpecializationTypeLoc>(T);
|
||||
SpecTL.setElaboratedKeywordLoc(SourceLocation());
|
||||
SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
|
||||
SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
|
||||
SpecTL.setTemplateNameLoc(TemplateNameLoc);
|
||||
SpecTL.setLAngleLoc(LAngleLoc);
|
||||
@ -883,8 +880,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
|
||||
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
|
||||
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
|
||||
|
||||
SS.Extend(Context, TemplateKWLoc, Builder.getTypeLocInContext(Context, T),
|
||||
CCLoc);
|
||||
SS.Extend(Context, Builder.getTypeLocInContext(Context, T), CCLoc);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -932,9 +928,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
|
||||
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
|
||||
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
|
||||
|
||||
|
||||
SS.Extend(Context, TemplateKWLoc, Builder.getTypeLocInContext(Context, T),
|
||||
CCLoc);
|
||||
SS.Extend(Context, Builder.getTypeLocInContext(Context, T), CCLoc);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1007,7 +1001,6 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
|
||||
|
||||
case NestedNameSpecifier::Identifier:
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
case NestedNameSpecifier::Super:
|
||||
// These are never namespace scopes.
|
||||
return true;
|
||||
|
@ -755,7 +755,7 @@ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
|
||||
Result = NestedNameSpecifier::Create(Context, Result, Namespace);
|
||||
} else if (const auto *TD = dyn_cast<TagDecl>(Parent))
|
||||
Result = NestedNameSpecifier::Create(
|
||||
Context, Result, false, Context.getTypeDeclType(TD).getTypePtr());
|
||||
Context, Result, Context.getTypeDeclType(TD).getTypePtr());
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
@ -1216,7 +1216,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
|
||||
NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
|
||||
else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
|
||||
R.Qualifier = NestedNameSpecifier::Create(
|
||||
SemaRef.Context, nullptr, false,
|
||||
SemaRef.Context, nullptr,
|
||||
SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
|
||||
else
|
||||
R.QualifierIsInformative = false;
|
||||
@ -1405,7 +1405,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
|
||||
NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
|
||||
else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))
|
||||
R.Qualifier = NestedNameSpecifier::Create(
|
||||
SemaRef.Context, nullptr, false,
|
||||
SemaRef.Context, nullptr,
|
||||
SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
|
||||
else
|
||||
R.QualifierIsInformative = false;
|
||||
|
@ -116,8 +116,7 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD,
|
||||
|
||||
auto buildElaboratedType = [&]() {
|
||||
auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, S.getStdNamespace());
|
||||
NNS = NestedNameSpecifier::Create(S.Context, NNS, false,
|
||||
CoroTrait.getTypePtr());
|
||||
NNS = NestedNameSpecifier::Create(S.Context, NNS, CoroTrait.getTypePtr());
|
||||
return S.Context.getElaboratedType(ElaboratedTypeKeyword::None, NNS,
|
||||
PromiseType);
|
||||
};
|
||||
|
@ -252,8 +252,8 @@ static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
|
||||
S.Diag(NameLoc, diag::ext_found_in_dependent_base) << &II;
|
||||
|
||||
ASTContext &Context = S.Context;
|
||||
auto *NNS = NestedNameSpecifier::Create(Context, nullptr, false,
|
||||
cast<Type>(Context.getRecordType(RD)));
|
||||
auto *NNS = NestedNameSpecifier::Create(
|
||||
Context, nullptr, cast<Type>(Context.getRecordType(RD)));
|
||||
QualType T =
|
||||
Context.getDependentNameType(ElaboratedTypeKeyword::Typename, NNS, &II);
|
||||
|
||||
@ -580,10 +580,10 @@ synthesizeCurrentNestedNameSpecifier(ASTContext &Context, DeclContext *DC) {
|
||||
auto *ND = dyn_cast<NamespaceDecl>(DC);
|
||||
if (ND && !ND->isInline() && !ND->isAnonymousNamespace())
|
||||
return NestedNameSpecifier::Create(Context, nullptr, ND);
|
||||
else if (auto *RD = dyn_cast<CXXRecordDecl>(DC))
|
||||
return NestedNameSpecifier::Create(Context, nullptr, RD->isTemplateDecl(),
|
||||
if (auto *RD = dyn_cast<CXXRecordDecl>(DC))
|
||||
return NestedNameSpecifier::Create(Context, nullptr,
|
||||
RD->getTypeForDecl());
|
||||
else if (isa<TranslationUnitDecl>(DC))
|
||||
if (isa<TranslationUnitDecl>(DC))
|
||||
return NestedNameSpecifier::GlobalSpecifier(Context);
|
||||
}
|
||||
llvm_unreachable("something isn't in TU scope?");
|
||||
@ -624,8 +624,7 @@ ParsedType Sema::ActOnMSVCUnknownTypeName(const IdentifierInfo &II,
|
||||
findRecordWithDependentBasesOfEnclosingMethod(CurContext)) {
|
||||
// Build a DependentNameType that will perform lookup into RD at
|
||||
// instantiation time.
|
||||
NNS = NestedNameSpecifier::Create(Context, nullptr, RD->isTemplateDecl(),
|
||||
RD->getTypeForDecl());
|
||||
NNS = NestedNameSpecifier::Create(Context, nullptr, RD->getTypeForDecl());
|
||||
|
||||
// Diagnose that this identifier was undeclared, and retry the lookup during
|
||||
// template instantiation.
|
||||
@ -6243,11 +6242,12 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
|
||||
|
||||
NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data());
|
||||
do {
|
||||
if (SpecLoc.getNestedNameSpecifier()->getKind() ==
|
||||
NestedNameSpecifier::TypeSpecWithTemplate)
|
||||
Diag(Loc, diag::ext_template_after_declarative_nns)
|
||||
<< FixItHint::CreateRemoval(
|
||||
SpecLoc.getTypeLoc().getTemplateKeywordLoc());
|
||||
if (TypeLoc TL = SpecLoc.getTypeLoc()) {
|
||||
if (SourceLocation TemplateKeywordLoc = TL.getTemplateKeywordLoc();
|
||||
TemplateKeywordLoc.isValid())
|
||||
Diag(Loc, diag::ext_template_after_declarative_nns)
|
||||
<< FixItHint::CreateRemoval(TemplateKeywordLoc);
|
||||
}
|
||||
|
||||
if (const Type *T = SpecLoc.getNestedNameSpecifier()->getAsType()) {
|
||||
if (const auto *TST = T->getAsAdjusted<TemplateSpecializationType>()) {
|
||||
|
@ -14799,8 +14799,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
|
||||
CXXScopeSpec SS;
|
||||
const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr());
|
||||
SS.MakeTrivial(S.Context,
|
||||
NestedNameSpecifier::Create(S.Context, nullptr, false,
|
||||
CanonicalT),
|
||||
NestedNameSpecifier::Create(S.Context, nullptr, CanonicalT),
|
||||
Loc);
|
||||
|
||||
// Create the reference to operator=.
|
||||
|
@ -2684,7 +2684,7 @@ recoverFromMSUnqualifiedLookup(Sema &S, ASTContext &Context,
|
||||
// perform name lookup during template instantiation.
|
||||
CXXScopeSpec SS;
|
||||
auto *NNS =
|
||||
NestedNameSpecifier::Create(Context, nullptr, true, RD->getTypeForDecl());
|
||||
NestedNameSpecifier::Create(Context, nullptr, RD->getTypeForDecl());
|
||||
SS.MakeTrivial(Context, NNS, SourceRange(Loc, Loc));
|
||||
return DependentScopeDeclRefExpr::Create(
|
||||
Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo,
|
||||
|
@ -508,7 +508,6 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
|
||||
switch (SS.getScopeRep()->getKind()) {
|
||||
case NestedNameSpecifier::Identifier:
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
// Per C++11 [over.literal]p2, literal operators can only be declared at
|
||||
// namespace scope. Therefore, this unqualified-id cannot name anything.
|
||||
// Reject it early, because we have no AST representation for this in the
|
||||
|
@ -4530,7 +4530,6 @@ static void getNestedNameSpecifierIdentifiers(
|
||||
II = NNS->getAsNamespaceAlias()->getIdentifier();
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
II = QualType(NNS->getAsType(), 0).getBaseTypeIdentifier();
|
||||
break;
|
||||
@ -4895,8 +4894,7 @@ TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier(
|
||||
NNS = NestedNameSpecifier::Create(Context, NNS, ND);
|
||||
++NumSpecifiers;
|
||||
} else if (auto *RD = dyn_cast_or_null<RecordDecl>(C)) {
|
||||
NNS = NestedNameSpecifier::Create(Context, NNS, RD->isTemplateDecl(),
|
||||
RD->getTypeForDecl());
|
||||
NNS = NestedNameSpecifier::Create(Context, NNS, RD->getTypeForDecl());
|
||||
++NumSpecifiers;
|
||||
}
|
||||
}
|
||||
|
@ -364,8 +364,8 @@ bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II,
|
||||
// The code is missing a 'template' keyword prior to the dependent template
|
||||
// name.
|
||||
NestedNameSpecifier *Qualifier = (NestedNameSpecifier *)SS->getScopeRep();
|
||||
SuggestedTemplate
|
||||
= TemplateTy::make(Context.getDependentTemplateName(Qualifier, &II));
|
||||
SuggestedTemplate = TemplateTy::make(Context.getDependentTemplateName(
|
||||
{Qualifier, &II, /*HasTemplateKeyword=*/false}));
|
||||
Diag(IILoc, diag::err_template_kw_missing)
|
||||
<< SuggestedTemplate.get()
|
||||
<< FixItHint::CreateInsertion(IILoc, "template ");
|
||||
@ -2777,7 +2777,8 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
|
||||
// Look one step prior in a dependent template specialization type.
|
||||
if (const DependentTemplateSpecializationType *DependentTST
|
||||
= T->getAs<DependentTemplateSpecializationType>()) {
|
||||
if (NestedNameSpecifier *NNS = DependentTST->getQualifier())
|
||||
if (NestedNameSpecifier *NNS =
|
||||
DependentTST->getDependentTemplateName().getQualifier())
|
||||
T = QualType(NNS->getAsType(), 0);
|
||||
else
|
||||
T = QualType();
|
||||
@ -3480,16 +3481,17 @@ Sema::findFailedBooleanCondition(Expr *Cond) {
|
||||
QualType Sema::CheckTemplateIdType(TemplateName Name,
|
||||
SourceLocation TemplateLoc,
|
||||
TemplateArgumentListInfo &TemplateArgs) {
|
||||
DependentTemplateName *DTN =
|
||||
Name.getUnderlying().getAsDependentTemplateName();
|
||||
if (DTN && DTN->isIdentifier())
|
||||
// FIXME: 'getUnderlying' loses SubstTemplateTemplateParm nodes from alias
|
||||
// template substitutions.
|
||||
if (DependentTemplateName *DTN =
|
||||
Name.getUnderlying().getAsDependentTemplateName();
|
||||
DTN && DTN->getName().getIdentifier())
|
||||
// When building a template-id where the template-name is dependent,
|
||||
// assume the template is a type template. Either our assumption is
|
||||
// correct, or the code is ill-formed and will be diagnosed when the
|
||||
// dependent name is substituted.
|
||||
return Context.getDependentTemplateSpecializationType(
|
||||
ElaboratedTypeKeyword::None, DTN->getQualifier(), DTN->getIdentifier(),
|
||||
TemplateArgs.arguments());
|
||||
ElaboratedTypeKeyword::None, *DTN, TemplateArgs.arguments());
|
||||
|
||||
if (Name.getAsAssumedTemplateName() &&
|
||||
resolveAssumedTemplateNameAsType(/*Scope=*/nullptr, Name, TemplateLoc))
|
||||
@ -3824,8 +3826,7 @@ TypeResult Sema::ActOnTemplateIdType(
|
||||
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
|
||||
assert(SS.getScopeRep() == DTN->getQualifier());
|
||||
QualType T = Context.getDependentTemplateSpecializationType(
|
||||
ElaboratedTypeKeyword::None, DTN->getQualifier(), DTN->getIdentifier(),
|
||||
TemplateArgs.arguments());
|
||||
ElaboratedTypeKeyword::None, *DTN, TemplateArgs.arguments());
|
||||
// Build type-source information.
|
||||
TypeLocBuilder TLB;
|
||||
DependentTemplateSpecializationTypeLoc SpecTL
|
||||
@ -3894,8 +3895,7 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
|
||||
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
|
||||
assert(SS.getScopeRep() == DTN->getQualifier());
|
||||
QualType T = Context.getDependentTemplateSpecializationType(
|
||||
Keyword, DTN->getQualifier(), DTN->getIdentifier(),
|
||||
TemplateArgs.arguments());
|
||||
Keyword, *DTN, TemplateArgs.arguments());
|
||||
|
||||
// Build type-source information.
|
||||
TypeLocBuilder TLB;
|
||||
@ -4812,13 +4812,14 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S,
|
||||
|
||||
switch (Name.getKind()) {
|
||||
case UnqualifiedIdKind::IK_Identifier:
|
||||
Result = TemplateTy::make(
|
||||
Context.getDependentTemplateName(Qualifier, Name.Identifier));
|
||||
Result = TemplateTy::make(Context.getDependentTemplateName(
|
||||
{Qualifier, Name.Identifier, TemplateKWLoc.isValid()}));
|
||||
return TNK_Dependent_template_name;
|
||||
|
||||
case UnqualifiedIdKind::IK_OperatorFunctionId:
|
||||
Result = TemplateTy::make(Context.getDependentTemplateName(
|
||||
Qualifier, Name.OperatorFunctionId.Operator));
|
||||
{Qualifier, Name.OperatorFunctionId.Operator,
|
||||
TemplateKWLoc.isValid()}));
|
||||
return TNK_Function_template;
|
||||
|
||||
case UnqualifiedIdKind::IK_LiteralOperatorId:
|
||||
@ -5332,7 +5333,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc,
|
||||
// know that we need a non-type template argument, convert this
|
||||
// template name into an expression.
|
||||
|
||||
DeclarationNameInfo NameInfo(DTN->getIdentifier(),
|
||||
DeclarationNameInfo NameInfo(DTN->getName().getIdentifier(),
|
||||
ArgLoc.getTemplateNameLoc());
|
||||
|
||||
CXXScopeSpec SS;
|
||||
@ -6071,8 +6072,9 @@ bool UnnamedLocalNoLinkageFinder::VisitDependentNameType(
|
||||
|
||||
bool UnnamedLocalNoLinkageFinder::VisitDependentTemplateSpecializationType(
|
||||
const DependentTemplateSpecializationType* T) {
|
||||
if (auto *Q = T->getQualifier())
|
||||
if (auto *Q = T->getDependentTemplateName().getQualifier())
|
||||
return VisitNestedNameSpecifier(Q);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -6154,7 +6156,6 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
|
||||
return false;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
return Visit(QualType(NNS->getAsType(), 0));
|
||||
}
|
||||
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
|
||||
@ -7526,9 +7527,8 @@ ExprResult Sema::BuildExpressionFromDeclTemplateArgument(
|
||||
isa<IndirectFieldDecl>(VD)));
|
||||
QualType ClassType
|
||||
= Context.getTypeDeclType(cast<RecordDecl>(VD->getDeclContext()));
|
||||
NestedNameSpecifier *Qualifier
|
||||
= NestedNameSpecifier::Create(Context, nullptr, false,
|
||||
ClassType.getTypePtr());
|
||||
NestedNameSpecifier *Qualifier =
|
||||
NestedNameSpecifier::Create(Context, nullptr, ClassType.getTypePtr());
|
||||
SS.MakeTrivial(Context, Qualifier, Loc);
|
||||
}
|
||||
|
||||
@ -10694,15 +10694,14 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
|
||||
assert(DTN && "dependent template has non-dependent name?");
|
||||
assert(DTN->getQualifier() == SS.getScopeRep());
|
||||
|
||||
if (!DTN->isIdentifier()) {
|
||||
if (!DTN->getName().getIdentifier()) {
|
||||
Diag(TemplateIILoc, diag::err_template_id_not_a_type) << Template;
|
||||
NoteAllFoundTemplates(Template);
|
||||
return true;
|
||||
}
|
||||
|
||||
QualType T = Context.getDependentTemplateSpecializationType(
|
||||
ElaboratedTypeKeyword::Typename, DTN->getQualifier(),
|
||||
DTN->getIdentifier(), TemplateArgs.arguments());
|
||||
ElaboratedTypeKeyword::Typename, *DTN, TemplateArgs.arguments());
|
||||
|
||||
// Create source-location information for this type.
|
||||
TypeLocBuilder Builder;
|
||||
|
@ -7031,7 +7031,8 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
|
||||
const DependentTemplateSpecializationType *Spec
|
||||
= cast<DependentTemplateSpecializationType>(T);
|
||||
|
||||
MarkUsedTemplateParameters(Ctx, Spec->getQualifier(),
|
||||
MarkUsedTemplateParameters(Ctx,
|
||||
Spec->getDependentTemplateName().getQualifier(),
|
||||
OnlyDeduced, Depth, Used);
|
||||
|
||||
for (const auto &Arg : Spec->template_arguments())
|
||||
|
@ -705,7 +705,7 @@ public:
|
||||
|
||||
QualType TransformDependentTemplateSpecializationType(
|
||||
TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL,
|
||||
NestedNameSpecifierLoc QualifierLoc);
|
||||
CXXScopeSpec &SS);
|
||||
|
||||
/// Transforms the parameters of a function type into the
|
||||
/// given vectors.
|
||||
@ -1132,38 +1132,21 @@ public:
|
||||
/// nested-name-specifier and the given type. Subclasses may override
|
||||
/// this routine to provide different behavior.
|
||||
QualType RebuildDependentTemplateSpecializationType(
|
||||
ElaboratedTypeKeyword Keyword,
|
||||
NestedNameSpecifierLoc QualifierLoc,
|
||||
SourceLocation TemplateKWLoc,
|
||||
const IdentifierInfo *Name,
|
||||
SourceLocation NameLoc,
|
||||
TemplateArgumentListInfo &Args,
|
||||
bool AllowInjectedClassName) {
|
||||
// Rebuild the template name.
|
||||
// TODO: avoid TemplateName abstraction
|
||||
CXXScopeSpec SS;
|
||||
SS.Adopt(QualifierLoc);
|
||||
TemplateName InstName = getDerived().RebuildTemplateName(
|
||||
SS, TemplateKWLoc, *Name, NameLoc, QualType(), nullptr,
|
||||
AllowInjectedClassName);
|
||||
|
||||
if (InstName.isNull())
|
||||
return QualType();
|
||||
|
||||
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
|
||||
SourceLocation TemplateKWLoc, TemplateName Name, SourceLocation NameLoc,
|
||||
TemplateArgumentListInfo &Args, bool AllowInjectedClassName) {
|
||||
// If it's still dependent, make a dependent specialization.
|
||||
if (InstName.getAsDependentTemplateName())
|
||||
if (const DependentTemplateStorage *S = Name.getAsDependentTemplateName())
|
||||
return SemaRef.Context.getDependentTemplateSpecializationType(
|
||||
Keyword, QualifierLoc.getNestedNameSpecifier(), Name,
|
||||
Args.arguments());
|
||||
Keyword, *S, Args.arguments());
|
||||
|
||||
// Otherwise, make an elaborated type wrapping a non-dependent
|
||||
// specialization.
|
||||
QualType T =
|
||||
getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args);
|
||||
getDerived().RebuildTemplateSpecializationType(Name, NameLoc, Args);
|
||||
if (T.isNull())
|
||||
return QualType();
|
||||
return SemaRef.Context.getElaboratedType(
|
||||
Keyword, QualifierLoc.getNestedNameSpecifier(), T);
|
||||
return SemaRef.Context.getElaboratedType(Keyword, NNS, T);
|
||||
}
|
||||
|
||||
/// Build a new typename type that refers to an identifier.
|
||||
@ -1332,6 +1315,13 @@ public:
|
||||
SourceLocation NameLoc, QualType ObjectType,
|
||||
bool AllowInjectedClassName);
|
||||
|
||||
TemplateName RebuildTemplateName(CXXScopeSpec &SS,
|
||||
SourceLocation TemplateKWLoc,
|
||||
IdentifierOrOverloadedOperator IO,
|
||||
SourceLocation NameLoc, QualType ObjectType,
|
||||
NamedDecl *FirstQualifierInScope,
|
||||
bool AllowInjectedClassName);
|
||||
|
||||
/// Build a new template name given a template template parameter pack
|
||||
/// and the
|
||||
///
|
||||
@ -4634,7 +4624,6 @@ NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
|
||||
break;
|
||||
}
|
||||
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
case NestedNameSpecifier::TypeSpec: {
|
||||
TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType,
|
||||
FirstQualifierInScope, SS);
|
||||
@ -4654,8 +4643,7 @@ NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
|
||||
TL = ETL.getNamedTypeLoc();
|
||||
}
|
||||
|
||||
SS.Extend(SemaRef.Context, TL.getTemplateKeywordLoc(), TL,
|
||||
Q.getLocalEndLoc());
|
||||
SS.Extend(SemaRef.Context, TL, Q.getLocalEndLoc());
|
||||
break;
|
||||
}
|
||||
// If the nested-name-specifier is an invalid type def, don't emit an
|
||||
@ -4753,6 +4741,22 @@ TreeTransform<Derived>
|
||||
llvm_unreachable("Unknown name kind.");
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
TemplateName TreeTransform<Derived>::RebuildTemplateName(
|
||||
CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
|
||||
IdentifierOrOverloadedOperator IO, SourceLocation NameLoc,
|
||||
QualType ObjectType, NamedDecl *FirstQualifierInScope,
|
||||
bool AllowInjectedClassName) {
|
||||
if (const IdentifierInfo *II = IO.getIdentifier()) {
|
||||
return getDerived().RebuildTemplateName(SS, TemplateKWLoc, *II, NameLoc,
|
||||
ObjectType, FirstQualifierInScope,
|
||||
AllowInjectedClassName);
|
||||
}
|
||||
return getDerived().RebuildTemplateName(SS, TemplateKWLoc, IO.getOperator(),
|
||||
NameLoc, ObjectType,
|
||||
AllowInjectedClassName);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
TemplateName
|
||||
TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
|
||||
@ -4794,20 +4798,9 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
|
||||
|
||||
// FIXME: Preserve the location of the "template" keyword.
|
||||
SourceLocation TemplateKWLoc = NameLoc;
|
||||
|
||||
if (DTN->isIdentifier()) {
|
||||
return getDerived().RebuildTemplateName(SS,
|
||||
TemplateKWLoc,
|
||||
*DTN->getIdentifier(),
|
||||
NameLoc,
|
||||
ObjectType,
|
||||
FirstQualifierInScope,
|
||||
AllowInjectedClassName);
|
||||
}
|
||||
|
||||
return getDerived().RebuildTemplateName(SS, TemplateKWLoc,
|
||||
DTN->getOperator(), NameLoc,
|
||||
ObjectType, AllowInjectedClassName);
|
||||
return getDerived().RebuildTemplateName(
|
||||
SS, TemplateKWLoc, DTN->getName(), NameLoc, ObjectType,
|
||||
FirstQualifierInScope, AllowInjectedClassName);
|
||||
}
|
||||
|
||||
// FIXME: Try to preserve more of the TemplateName.
|
||||
@ -5401,13 +5394,14 @@ TypeSourceInfo *TreeTransform<Derived>::TransformTSIInObjectScope(
|
||||
DependentTemplateSpecializationTypeLoc SpecTL =
|
||||
TL.castAs<DependentTemplateSpecializationTypeLoc>();
|
||||
|
||||
TemplateName Template
|
||||
= getDerived().RebuildTemplateName(SS,
|
||||
SpecTL.getTemplateKeywordLoc(),
|
||||
*SpecTL.getTypePtr()->getIdentifier(),
|
||||
SpecTL.getTemplateNameLoc(),
|
||||
ObjectType, UnqualLookup,
|
||||
/*AllowInjectedClassName*/true);
|
||||
const IdentifierInfo *II = SpecTL.getTypePtr()
|
||||
->getDependentTemplateName()
|
||||
.getName()
|
||||
.getIdentifier();
|
||||
TemplateName Template = getDerived().RebuildTemplateName(
|
||||
SS, SpecTL.getTemplateKeywordLoc(), *II, SpecTL.getTemplateNameLoc(),
|
||||
ObjectType, UnqualLookup,
|
||||
/*AllowInjectedClassName*/ true);
|
||||
if (Template.isNull())
|
||||
return nullptr;
|
||||
|
||||
@ -7430,9 +7424,9 @@ QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType(
|
||||
// FIXME: maybe don't rebuild if all the template arguments are the same.
|
||||
|
||||
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
|
||||
assert(DTN->getQualifier() == SS.getScopeRep());
|
||||
QualType Result = getSema().Context.getDependentTemplateSpecializationType(
|
||||
TL.getTypePtr()->getKeyword(), DTN->getQualifier(),
|
||||
DTN->getIdentifier(), NewTemplateArgs.arguments());
|
||||
TL.getTypePtr()->getKeyword(), *DTN, NewTemplateArgs.arguments());
|
||||
|
||||
DependentTemplateSpecializationTypeLoc NewTL
|
||||
= TLB.push<DependentTemplateSpecializationTypeLoc>(Result);
|
||||
@ -7755,15 +7749,15 @@ QualType TreeTransform<Derived>::
|
||||
return QualType();
|
||||
}
|
||||
|
||||
return getDerived()
|
||||
.TransformDependentTemplateSpecializationType(TLB, TL, QualifierLoc);
|
||||
CXXScopeSpec SS;
|
||||
SS.Adopt(QualifierLoc);
|
||||
return getDerived().TransformDependentTemplateSpecializationType(TLB, TL, SS);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
QualType TreeTransform<Derived>::
|
||||
TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
|
||||
DependentTemplateSpecializationTypeLoc TL,
|
||||
NestedNameSpecifierLoc QualifierLoc) {
|
||||
template <typename Derived>
|
||||
QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType(
|
||||
TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL,
|
||||
CXXScopeSpec &SS) {
|
||||
const DependentTemplateSpecializationType *T = TL.getTypePtr();
|
||||
|
||||
TemplateArgumentListInfo NewTemplateArgs;
|
||||
@ -7777,13 +7771,25 @@ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
|
||||
NewTemplateArgs))
|
||||
return QualType();
|
||||
|
||||
QualType Result = getDerived().RebuildDependentTemplateSpecializationType(
|
||||
T->getKeyword(), QualifierLoc, TL.getTemplateKeywordLoc(),
|
||||
T->getIdentifier(), TL.getTemplateNameLoc(), NewTemplateArgs,
|
||||
/*AllowInjectedClassName*/ false);
|
||||
if (Result.isNull())
|
||||
return QualType();
|
||||
const DependentTemplateStorage &DTN = T->getDependentTemplateName();
|
||||
|
||||
QualType Result = TL.getType();
|
||||
if (getDerived().AlwaysRebuild() || SS.getScopeRep() != DTN.getQualifier()) {
|
||||
TemplateName Name = getDerived().RebuildTemplateName(
|
||||
SS, TL.getTemplateKeywordLoc(), DTN.getName(), TL.getTemplateNameLoc(),
|
||||
/*ObjectType=*/QualType(), /*FirstQualifierInScope=*/nullptr,
|
||||
/*AllowInjectedClassName=*/false);
|
||||
if (Name.isNull())
|
||||
return QualType();
|
||||
Result = getDerived().RebuildDependentTemplateSpecializationType(
|
||||
T->getKeyword(), SS.getScopeRep(), TL.getTemplateKeywordLoc(), Name,
|
||||
TL.getTemplateNameLoc(), NewTemplateArgs,
|
||||
/*AllowInjectedClassName=*/false);
|
||||
if (Result.isNull())
|
||||
return QualType();
|
||||
}
|
||||
|
||||
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(SemaRef.Context);
|
||||
if (const ElaboratedType *ElabT = dyn_cast<ElaboratedType>(Result)) {
|
||||
QualType NamedT = ElabT->getNamedType();
|
||||
|
||||
@ -7801,7 +7807,8 @@ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
|
||||
ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result);
|
||||
NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc());
|
||||
NewTL.setQualifierLoc(QualifierLoc);
|
||||
} else if (isa<DependentTemplateSpecializationType>(Result)) {
|
||||
} else {
|
||||
assert(isa<DependentTemplateSpecializationType>(Result));
|
||||
DependentTemplateSpecializationTypeLoc SpecTL
|
||||
= TLB.push<DependentTemplateSpecializationTypeLoc>(Result);
|
||||
SpecTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc());
|
||||
@ -7812,15 +7819,6 @@ TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB,
|
||||
SpecTL.setRAngleLoc(TL.getRAngleLoc());
|
||||
for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I)
|
||||
SpecTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo());
|
||||
} else {
|
||||
TemplateSpecializationTypeLoc SpecTL
|
||||
= TLB.push<TemplateSpecializationTypeLoc>(Result);
|
||||
SpecTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc());
|
||||
SpecTL.setTemplateNameLoc(TL.getTemplateNameLoc());
|
||||
SpecTL.setLAngleLoc(TL.getLAngleLoc());
|
||||
SpecTL.setRAngleLoc(TL.getRAngleLoc());
|
||||
for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I)
|
||||
SpecTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo());
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
@ -17532,8 +17530,7 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base,
|
||||
<< ScopeType->getType() << getSema().getLangOpts().CPlusPlus;
|
||||
return ExprError();
|
||||
}
|
||||
SS.Extend(SemaRef.Context, SourceLocation(), ScopeType->getTypeLoc(),
|
||||
CCLoc);
|
||||
SS.Extend(SemaRef.Context, ScopeType->getTypeLoc(), CCLoc);
|
||||
}
|
||||
|
||||
SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller.
|
||||
|
@ -9914,18 +9914,12 @@ ASTRecordReader::readNestedNameSpecifierLoc() {
|
||||
break;
|
||||
}
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate: {
|
||||
bool Template = readBool();
|
||||
case NestedNameSpecifier::TypeSpec: {
|
||||
TypeSourceInfo *T = readTypeSourceInfo();
|
||||
if (!T)
|
||||
return NestedNameSpecifierLoc();
|
||||
SourceLocation ColonColonLoc = readSourceLocation();
|
||||
|
||||
// FIXME: 'template' keyword location not saved anywhere, so we fake it.
|
||||
Builder.Extend(Context,
|
||||
Template? T->getTypeLoc().getBeginLoc() : SourceLocation(),
|
||||
T->getTypeLoc(), ColonColonLoc);
|
||||
Builder.Extend(Context, T->getTypeLoc(), ColonColonLoc);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -7022,8 +7022,6 @@ void ASTRecordWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
Record->push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate);
|
||||
AddTypeRef(NNS.getTypeLoc().getType());
|
||||
AddTypeLoc(NNS.getTypeLoc());
|
||||
AddSourceLocation(NNS.getLocalSourceRange().getEnd());
|
||||
|
@ -959,8 +959,6 @@ public:
|
||||
case NestedNameSpecifier::NamespaceAlias:
|
||||
case NestedNameSpecifier::Identifier:
|
||||
return syntax::NodeKind::IdentifierNameSpecifier;
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
return syntax::NodeKind::SimpleTemplateNameSpecifier;
|
||||
case NestedNameSpecifier::TypeSpec: {
|
||||
const auto *NNSType = NNS.getAsType();
|
||||
assert(NNSType);
|
||||
|
@ -351,8 +351,8 @@ namespace testClassTemplateDecl {
|
||||
// CHECK-NEXT: | |-CXXDestructorDecl 0x{{.+}} <line:[[@LINE-67]]:5, col:24> col:5 used ~TestClassTemplate 'void () noexcept' implicit_instantiation instantiated_from 0x[[#TEMPLATE_DESTRUCTOR_DECL]]{{$}}
|
||||
// CHECK-NEXT: | |-CXXMethodDecl 0x{{.+}} <line:[[@LINE-67]]:5, col:11> col:9 j 'int ()' implicit_instantiation instantiated_from 0x[[#TEMPLATE_METHOD_DECL]]{{$}}
|
||||
// CHECK-NEXT: | |-FieldDecl 0x{{.+}} <line:[[@LINE-67]]:5, col:9> col:9 i 'int'{{$}}
|
||||
// CHECK-NEXT: | `-CXXConstructorDecl 0x{{.+}} <line:[[@LINE-73]]:30> col:30 implicit constexpr TestClassTemplate 'void (const TestClassTemplate<A> &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
|
||||
// CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} <col:30> col:30 'const TestClassTemplate<A> &'{{$}}
|
||||
// CHECK-NEXT: | `-CXXConstructorDecl 0x{{.+}} <line:[[@LINE-73]]:30> col:30 implicit constexpr TestClassTemplate 'void (const TestClassTemplate<testClassTemplateDecl::A> &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
|
||||
// CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} <col:30> col:30 'const TestClassTemplate<testClassTemplateDecl::A> &'{{$}}
|
||||
// CHECK-NEXT: |-ClassTemplateSpecialization 0x{{.+}} 'TestClassTemplate'{{$}}
|
||||
// CHECK-NEXT: |-ClassTemplateSpecialization 0x{{.+}} 'TestClassTemplate'{{$}}
|
||||
// CHECK-NEXT: `-ClassTemplateSpecialization 0x{{.+}} 'TestClassTemplate'{{$}}
|
||||
@ -654,10 +654,10 @@ namespace testCanonicalTemplate {
|
||||
// CHECK-NEXT: | `-ClassTemplateSpecialization 0x{{.+}} 'TestClassTemplate'{{$}}
|
||||
// CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} <line:[[@LINE-36]]:31> col:31 implicit used constexpr TestClassTemplate 'void () noexcept' inline default trivial{{$}}
|
||||
// CHECK-NEXT: | `-CompoundStmt 0x{{.+}} <col:31>{{$}}
|
||||
// CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate 'void (const TestClassTemplate<A> &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
|
||||
// CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} <col:31> col:31 'const TestClassTemplate<A> &'{{$}}
|
||||
// CHECK-NEXT: `-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate 'void (TestClassTemplate<A> &&)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
|
||||
// CHECK-NEXT: `-ParmVarDecl 0x{{.+}} <col:31> col:31 'TestClassTemplate<A> &&'{{$}}
|
||||
// CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate 'void (const TestClassTemplate<testCanonicalTemplate::A> &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
|
||||
// CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} <col:31> col:31 'const TestClassTemplate<testCanonicalTemplate::A> &'{{$}}
|
||||
// CHECK-NEXT: `-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate 'void (TestClassTemplate<testCanonicalTemplate::A> &&)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
|
||||
// CHECK-NEXT: `-ParmVarDecl 0x{{.+}} <col:31> col:31 'TestClassTemplate<testCanonicalTemplate::A> &&'{{$}}
|
||||
|
||||
|
||||
template<typename T1> class TestClassTemplate2;
|
||||
@ -682,10 +682,10 @@ namespace testCanonicalTemplate {
|
||||
// CHECK-NEXT: |-CXXRecordDecl 0x{{.+}} <col:25, col:31> col:31 implicit class TestClassTemplate2{{$}}
|
||||
// CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit used constexpr TestClassTemplate2 'void () noexcept' inline default trivial{{$}}
|
||||
// CHECK-NEXT: | `-CompoundStmt 0x{{.+}} <col:31>{{$}}
|
||||
// CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate2 'void (const TestClassTemplate2<A> &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
|
||||
// CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} <col:31> col:31 'const TestClassTemplate2<A> &'{{$}}
|
||||
// CHECK-NEXT: `-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate2 'void (TestClassTemplate2<A> &&)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
|
||||
// CHECK-NEXT: `-ParmVarDecl 0x{{.+}} <col:31> col:31 'TestClassTemplate2<A> &&'{{$}}
|
||||
// CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate2 'void (const TestClassTemplate2<testCanonicalTemplate::A> &)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
|
||||
// CHECK-NEXT: | `-ParmVarDecl 0x{{.+}} <col:31> col:31 'const TestClassTemplate2<testCanonicalTemplate::A> &'{{$}}
|
||||
// CHECK-NEXT: `-CXXConstructorDecl 0x{{.+}} <col:31> col:31 implicit constexpr TestClassTemplate2 'void (TestClassTemplate2<testCanonicalTemplate::A> &&)' inline default trivial noexcept-unevaluated 0x{{.+}}{{$}}
|
||||
// CHECK-NEXT: `-ParmVarDecl 0x{{.+}} <col:31> col:31 'TestClassTemplate2<testCanonicalTemplate::A> &&'{{$}}
|
||||
|
||||
// CHECK: ClassTemplateDecl 0x{{.+}} prev 0x{{.+}} <{{.+}}:[[@LINE-26]]:3, col:31> col:31 TestClassTemplate2{{$}}
|
||||
// CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <col:12, col:21> col:21 typename depth 0 index 0 T1{{$}}
|
||||
|
@ -229,11 +229,10 @@ void PostfixExpressions(S a, S *p, U<int> *r) {
|
||||
// CHECK-NEXT: ImplicitCastExpr
|
||||
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'S *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'S *'
|
||||
|
||||
// FIXME: there is no mention that this used the template keyword.
|
||||
r->template U<int>::~U();
|
||||
// CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:26> 'void'
|
||||
// CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:24> '<bound member function type>' ->~U 0x{{[^ ]*}}
|
||||
// CHECK-NEXT: NestedNameSpecifier TypeSpecWithTemplate 'template U<int>':'U<int>'
|
||||
// CHECK-NEXT: NestedNameSpecifier TypeSpec 'template U<int>':'U<int>'
|
||||
// CHECK-NEXT: ImplicitCastExpr
|
||||
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'U<int> *' lvalue ParmVar 0x{{[^ ]*}} 'r' 'U<int> *'
|
||||
|
||||
|
@ -174,7 +174,7 @@ namespace TestDependentMemberPointer {
|
||||
// DUMP-NEXT: | `-BuiltinType {{.+}} 'int'
|
||||
// DUMP-NEXT: `-TypeAliasDecl {{.+}} Z 'int U::template V<int>::*'{{$}}
|
||||
// DUMP-NEXT: `-MemberPointerType {{.+}} 'int U::template V<int>::*' dependent
|
||||
// DUMP-NEXT: |-DependentTemplateSpecializationType {{.+}} 'U::template V<int>' dependent
|
||||
// DUMP-NEXT: |-DependentTemplateSpecializationType {{.+}} 'template V<int>' dependent
|
||||
// DUMP-NEXT: `-BuiltinType {{.+}} 'int'
|
||||
} // namespace TestDependentMemberPointer
|
||||
|
||||
@ -6588,7 +6588,7 @@ namespace TestDependentMemberPointer {
|
||||
// JSON-NEXT: "tokLen": 9
|
||||
// JSON-NEXT: },
|
||||
// JSON-NEXT: "end": {
|
||||
// JSON-NEXT: "offset": 6359,
|
||||
// JSON-NEXT: "offset": 6356,
|
||||
// JSON-NEXT: "line": 179,
|
||||
// JSON-NEXT: "col": 1,
|
||||
// JSON-NEXT: "tokLen": 1
|
||||
@ -6896,7 +6896,7 @@ namespace TestDependentMemberPointer {
|
||||
// JSON-NEXT: "id": "0x{{.*}}",
|
||||
// JSON-NEXT: "kind": "DependentTemplateSpecializationType",
|
||||
// JSON-NEXT: "type": {
|
||||
// JSON-NEXT: "qualType": "U::template V<int>"
|
||||
// JSON-NEXT: "qualType": "template V<int>"
|
||||
// JSON-NEXT: },
|
||||
// JSON-NEXT: "isDependent": true,
|
||||
// JSON-NEXT: "isInstantiationDependent": true
|
||||
|
@ -92,7 +92,7 @@ namespace test3 {
|
||||
|
||||
template <class T> class Outer::A<T, typename T::nature> {
|
||||
public:
|
||||
static void foo(); // expected-note {{'Outer::A<B, Green>::foo' declared here}}
|
||||
static void foo(); // expected-note {{'Outer::A<test3::B, test3::Green>::foo' declared here}}
|
||||
};
|
||||
|
||||
class B {
|
||||
@ -102,7 +102,7 @@ namespace test3 {
|
||||
|
||||
void test() {
|
||||
Outer::A<B, Green>::foo();
|
||||
Outer::A<B, Blue>::foo(); // expected-error {{no member named 'foo' in 'test3::Outer::A<test3::B, test3::Blue>'; did you mean 'Outer::A<B, Green>::foo'?}}
|
||||
Outer::A<B, Blue>::foo(); // expected-error {{no member named 'foo' in 'test3::Outer::A<test3::B, test3::Blue>'; did you mean 'Outer::A<test3::B, test3::Green>::foo'?}}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,8 +98,8 @@ public:
|
||||
|
||||
void foo() { Templ<Derived> x(&Derived::func); }
|
||||
// expected-error@-1 {{no matching constructor for initialization of 'Templ<Derived>'}}
|
||||
// expected-note@#cwg203-ex3-Templ {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int (Derived::*)() const' (aka 'int (Base::*)() const') to 'const Templ<Derived>' for 1st argument}}
|
||||
// since-cxx11-note@#cwg203-ex3-Templ {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int (Derived::*)() const' (aka 'int (Base::*)() const') to 'Templ<Derived>' for 1st argument}}
|
||||
// expected-note@#cwg203-ex3-Templ {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int (Derived::*)() const' (aka 'int (Base::*)() const') to 'const Templ<cwg203::ex3::Derived>' for 1st argument}}
|
||||
// since-cxx11-note@#cwg203-ex3-Templ {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int (Derived::*)() const' (aka 'int (Base::*)() const') to 'Templ<cwg203::ex3::Derived>' for 1st argument}}
|
||||
// expected-note@#cwg203-ex3-Templ-ctor {{candidate template ignored: could not match 'cwg203::ex3::Derived' against 'cwg203::ex3::Base'}}
|
||||
} // namespace ex3
|
||||
|
||||
|
@ -150,7 +150,7 @@ void func() {
|
||||
// expected-note@#bar {{while substituting template arguments into constraint expression here}}
|
||||
// expected-note@#bar {{while checking the satisfaction of nested requirement requested here}}
|
||||
// expected-note@#bar {{candidate template ignored: constraints not satisfied [with T = False]}}
|
||||
// expected-note@#bar {{because 'X<False>::value' evaluated to false}}
|
||||
// expected-note@#bar {{because 'X<SubstitutionFailureNestedRequires::ErrorExpressions_NotSF::False>::value' evaluated to false}}
|
||||
|
||||
bar<int>();
|
||||
// expected-note@-1 {{while checking constraint satisfaction for template 'bar<int>' required here}} \
|
||||
|
@ -196,8 +196,10 @@ struct NestedTemplates1 {
|
||||
|
||||
template <typename T, typename U, int a>
|
||||
void foo2() {
|
||||
// FIXME: Here the template keyword is dropped because the failed condition
|
||||
// for a static assert is always printed with canonical types.
|
||||
static_assert(::ns::NestedTemplates1<T, a>::NestedTemplates2::template NestedTemplates3<U>::value, "message");
|
||||
// expected-error@-1{{static assertion failed due to requirement '::ns::NestedTemplates1<int, 3>::NestedTemplates2::template NestedTemplates3<float>::value': message}}
|
||||
// expected-error@-1{{static assertion failed due to requirement '::ns::NestedTemplates1<int, 3>::NestedTemplates2::NestedTemplates3<float>::value': message}}
|
||||
}
|
||||
template void foo2<int, float, 3>();
|
||||
// expected-note@-1{{in instantiation of function template specialization 'foo2<int, float, 3>' requested here}}
|
||||
|
@ -331,7 +331,7 @@ namespace DeduceArity {
|
||||
// CHECK: | |-ParmVarDecl {{.*}} 'Types<T...>'
|
||||
// CHECK: | `-ParmVarDecl {{.*}} 'T...' pack
|
||||
// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for F>
|
||||
// CHECK-SAME: 'auto (Types<X, Y, Z>, DeduceArity::X, DeduceArity::Y, DeduceArity::Z) ->
|
||||
// CHECK-SAME: 'auto (Types<DeduceArity::X, DeduceArity::Y, DeduceArity::Z>, DeduceArity::X, DeduceArity::Y, DeduceArity::Z) ->
|
||||
// CHECK-SAME: DeduceArity::F<DeduceArity::X, DeduceArity::Y, DeduceArity::Z>'
|
||||
// CHECK: | |-TemplateArgument pack
|
||||
// CHECK: | | |-TemplateArgument type 'DeduceArity::X'
|
||||
@ -343,16 +343,16 @@ namespace DeduceArity {
|
||||
// CHECK: | | `-TemplateArgument type 'DeduceArity::Z'
|
||||
// CHECK: | | `-RecordType {{.*}} 'DeduceArity::Z'
|
||||
// CHECK: | | `-CXXRecord {{.*}} 'Z'
|
||||
// CHECK: | |-ParmVarDecl {{.*}} 'Types<X, Y, Z>':'DeduceArity::Types<DeduceArity::X, DeduceArity::Y, DeduceArity::Z>'
|
||||
// CHECK: | |-ParmVarDecl {{.*}} 'Types<DeduceArity::X, DeduceArity::Y, DeduceArity::Z>':'DeduceArity::Types<DeduceArity::X, DeduceArity::Y, DeduceArity::Z>'
|
||||
// CHECK: | |-ParmVarDecl {{.*}} 'DeduceArity::X'
|
||||
// CHECK: | |-ParmVarDecl {{.*}} 'DeduceArity::Y'
|
||||
// CHECK: | `-ParmVarDecl {{.*}} 'DeduceArity::Z'
|
||||
// CHECK: `-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for F> 'auto (Types<X>, DeduceArity::X) -> DeduceArity::F<DeduceArity::X>'
|
||||
// CHECK: `-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for F> 'auto (Types<DeduceArity::X>, DeduceArity::X) -> DeduceArity::F<DeduceArity::X>'
|
||||
// CHECK: |-TemplateArgument pack
|
||||
// CHECK: | `-TemplateArgument type 'DeduceArity::X'
|
||||
// CHECK: | `-RecordType {{.*}} 'DeduceArity::X'
|
||||
// CHECK: | `-CXXRecord {{.*}} 'X'
|
||||
// CHECK: |-ParmVarDecl {{.*}} 'Types<X>':'DeduceArity::Types<DeduceArity::X>'
|
||||
// CHECK: |-ParmVarDecl {{.*}} 'Types<DeduceArity::X>':'DeduceArity::Types<DeduceArity::X>'
|
||||
// CHECK: `-ParmVarDecl {{.*}} 'DeduceArity::X'
|
||||
// CHECK: FunctionProtoType {{.*}} 'auto (Types<T...>, T...) -> F<T...>' dependent trailing_return cdecl
|
||||
// CHECK: |-InjectedClassNameType {{.*}} 'F<T...>' dependent
|
||||
|
@ -134,3 +134,21 @@ namespace PR9401 {
|
||||
const D<typename C<S, T>::template B<U>::template E<D<F> > >
|
||||
A<S, T>::B<U>::a = typename C<S, T>::template B<U>::template E<D<F> >(g);
|
||||
}
|
||||
|
||||
namespace templ_spec {
|
||||
template <class U> using A = void; // expected-note 2{{template parameter is declared here}}
|
||||
template <class T> struct B {
|
||||
A<typename T::template X<int>> t1;
|
||||
// expected-error@-1 {{'A<typename T::template X<int>>' (aka 'void')}}
|
||||
|
||||
A<typename T::X<int>> t2; // expected-error {{use 'template' keyword}}
|
||||
// expected-error@-1 {{'A<typename T::X<int>>' (aka 'void')}}
|
||||
|
||||
// FIXME: Why error recovery for the non-typename case is so bad?
|
||||
A<T::template X<int>> t3; // expected-error {{did you forget 'typename'}}
|
||||
// expected-error@-1 {{'A<typename T::X>' (aka 'void')}}
|
||||
|
||||
A<T::X<int>> t4; // expected-error {{use 'template' keyword}} expected-error {{did you forget 'typename'}}
|
||||
// expected-error@-1 {{'A<typename T::X>' (aka 'void')}}
|
||||
};
|
||||
} // namespace templ_spec
|
||||
|
@ -72,8 +72,8 @@ namespace type_requirement {
|
||||
|
||||
template<typename T> requires
|
||||
false_v<requires { typename T::template temp<T>; }>
|
||||
// expected-note@-1 {{because 'false_v<requires { typename contains_template<int>::template temp<contains_template<int> >; }>' evaluated to false}}
|
||||
// expected-note@-2 {{because 'false_v<requires { typename contains_template<short>::template temp<contains_template<short> >; }>' evaluated to false}}
|
||||
// expected-note@-1 {{because 'false_v<requires { typename contains_template<int>::template temp<type_requirement::contains_template<int> >; }>' evaluated to false}}
|
||||
// expected-note@-2 {{because 'false_v<requires { typename contains_template<short>::template temp<type_requirement::contains_template<short> >; }>' evaluated to false}}
|
||||
struct r2 {};
|
||||
|
||||
using r2i1 = r2<contains_template<int>>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template<int>]}}
|
||||
|
@ -1457,7 +1457,6 @@ bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS,
|
||||
break;
|
||||
}
|
||||
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
case NestedNameSpecifier::Global:
|
||||
case NestedNameSpecifier::Identifier:
|
||||
case NestedNameSpecifier::Super:
|
||||
@ -1492,7 +1491,6 @@ bool CursorVisitor::VisitNestedNameSpecifierLoc(
|
||||
break;
|
||||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
if (Visit(Q.getTypeLoc()))
|
||||
return true;
|
||||
|
||||
|
@ -61,7 +61,7 @@ using E = test<std::array<NotALiteral, 1>{}>;
|
||||
// expected-error@-1 {{non-type template parameter has non-literal type 'std::array<NotALiteral, 1>'}}
|
||||
|
||||
using F = test<std::array<std::string, 2>{}>;
|
||||
// expected-error@-1 {{type 'std::array<string, 2>' (aka 'std::array<std::string, 2>') of non-type template parameter is not a structural type}}
|
||||
// expected-error-re@-1 {{type 'std::array<{{(std::)?}}string, 2>'{{( \(aka 'std::array<std::string, 2>'\))?}} of non-type template parameter is not a structural type}}
|
||||
} // namespace test_ctad
|
||||
|
||||
namespace test_auto {
|
||||
|
@ -26,7 +26,7 @@ int main(int, char**) {
|
||||
|
||||
// expected-error-re@*:* {{static assertion failed due to requirement {{.*}}std::shared_ptr<> is not supported}}
|
||||
std::ignore = std::inout_ptr(sPtr);
|
||||
// expected-error@*:* {{no matching conversion for functional-style cast from 'std::shared_ptr<int>' to 'std::inout_ptr_t<shared_ptr<int>, _Ptr>' (aka 'inout_ptr_t<std::shared_ptr<int>, int *>'}}
|
||||
// expected-error-re@*:* {{no matching conversion for functional-style cast from 'std::shared_ptr<int>' to 'std::inout_ptr_t<{{(std::)?}}shared_ptr<int>, _Ptr>'{{( \(aka 'inout_ptr_t<std::shared_ptr<int>, int *>')?}}}}
|
||||
std::ignore = std::inout_ptr<int*>(sPtr);
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ int main(int, char**) {
|
||||
|
||||
// expected-error-re@*:* {{static assertion failed due to requirement {{.*}}Using std::shared_ptr<> without a deleter in std::out_ptr is not supported.}}
|
||||
std::ignore = std::out_ptr(sPtr);
|
||||
// expected-error@*:* {{no matching conversion for functional-style cast from 'std::shared_ptr<int>' to 'std::out_ptr_t<shared_ptr<int>, _Ptr>' (aka 'out_ptr_t<std::shared_ptr<int>, int *>')}}
|
||||
// expected-error-re@*:* {{no matching conversion for functional-style cast from 'std::shared_ptr<int>' to 'std::out_ptr_t<{{(std::)?}}shared_ptr<int>, _Ptr>'{{( \(aka 'out_ptr_t<std::shared_ptr<int>, int *>'\))?}}}}
|
||||
std::ignore = std::out_ptr<int*>(sPtr);
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ using H = test<std::pair<NotALiteral, NotALiteral>{}>;
|
||||
// expected-error@-1 {{non-type template parameter has non-literal type 'std::pair<NotALiteral, NotALiteral>'}}
|
||||
|
||||
using I = test<std::pair<std::string, std::string>{}>;
|
||||
// expected-error@-1 {{type 'std::pair<string, string>' (aka 'std::pair<std::string, std::string>') of non-type template parameter is not a structural type}}
|
||||
// expected-error-re@-1 {{type 'std::pair<{{(std::)?}}string, {{(std::)?}}string>'{{( \(aka 'std::pair<std::string, std::string>'\))?}} of non-type template parameter is not a structural type}}
|
||||
} // namespace test_ctad
|
||||
|
||||
namespace test_auto {
|
||||
|
Loading…
x
Reference in New Issue
Block a user