100 changes: 53 additions & 47 deletions clang/include/clang/AST/TemplateBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TrailingObjects.h"

namespace llvm {
class FoldingSetNodeID;
Expand Down Expand Up @@ -562,74 +563,78 @@ class TemplateArgumentListInfo {
/// the "<int>" in "sort<int>".
/// This is safe to be used inside an AST node, in contrast with
/// TemplateArgumentListInfo.
struct ASTTemplateArgumentListInfo {
struct ASTTemplateArgumentListInfo final
: private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
TemplateArgumentLoc> {
private:
friend TrailingObjects;

ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);

public:
/// \brief The source location of the left angle bracket ('<').
SourceLocation LAngleLoc;

/// \brief The source location of the right angle bracket ('>').
SourceLocation RAngleLoc;

union {
/// \brief The number of template arguments in TemplateArgs.
/// The actual template arguments (if any) are stored after the
/// ExplicitTemplateArgumentList structure.
unsigned NumTemplateArgs;

/// Force ASTTemplateArgumentListInfo to the right alignment
/// for the following array of TemplateArgumentLocs.
llvm::AlignedCharArray<
llvm::AlignOf<TemplateArgumentLoc>::Alignment, 1> Aligner;
};

/// \brief Retrieve the template arguments
TemplateArgumentLoc *getTemplateArgs() {
return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
}

/// \brief The number of template arguments in TemplateArgs.
unsigned NumTemplateArgs;

/// \brief Retrieve the template arguments
const TemplateArgumentLoc *getTemplateArgs() const {
return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
return getTrailingObjects<TemplateArgumentLoc>();
}

const TemplateArgumentLoc &operator[](unsigned I) const {
return getTemplateArgs()[I];
}

static const ASTTemplateArgumentListInfo *Create(ASTContext &C,
const TemplateArgumentListInfo &List);

void initializeFrom(const TemplateArgumentListInfo &List);
void initializeFrom(const TemplateArgumentListInfo &List,
bool &Dependent, bool &InstantiationDependent,
bool &ContainsUnexpandedParameterPack);
void copyInto(TemplateArgumentListInfo &List) const;
static std::size_t sizeFor(unsigned NumTemplateArgs);
static const ASTTemplateArgumentListInfo *
Create(ASTContext &C, const TemplateArgumentListInfo &List);
};

/// \brief Extends ASTTemplateArgumentListInfo with the source location
/// information for the template keyword; this is used as part of the
/// representation of qualified identifiers, such as S<T>::template apply<T>.
struct ASTTemplateKWAndArgsInfo : public ASTTemplateArgumentListInfo {
typedef ASTTemplateArgumentListInfo Base;
/// \brief Represents an explicit template argument list in C++, e.g.,
/// the "<int>" in "sort<int>". This is safe to be used inside an AST
/// node, in contrast with TemplateArgumentListInfo.
///
/// This is currently very similar to ASTTemplateArgumentListInfo
/// class, but a) has a extra member, TemplateKWLoc, and b) is
/// intended to be tacked on the end of some of the Expr classes, not
/// as a public interface.
struct ASTTemplateKWAndArgsInfo final
: private llvm::TrailingObjects<ASTTemplateKWAndArgsInfo,
TemplateArgumentLoc> {
friend TrailingObjects;

/// \brief The source location of the left angle bracket ('<').
SourceLocation LAngleLoc;

/// \brief The source location of the right angle bracket ('>').
SourceLocation RAngleLoc;

/// \brief The source location of the template keyword; this is used
/// as part of the representation of qualified identifiers, such as
/// S<T>::template apply<T>. Will be empty if this expression does
/// not have a template keyword.
SourceLocation TemplateKWLoc;

// NOTE: the source location of the (optional) template keyword is
// stored after all template arguments.
/// \brief The number of template arguments in TemplateArgs.
unsigned NumTemplateArgs;

/// \brief Get the source location of the template keyword.
SourceLocation getTemplateKeywordLoc() const {
return *reinterpret_cast<const SourceLocation*>
(getTemplateArgs() + NumTemplateArgs);
/// \brief Retrieve the template arguments
TemplateArgumentLoc *getTemplateArgs() {
return getTrailingObjects<TemplateArgumentLoc>();
}

/// \brief Sets the source location of the template keyword.
void setTemplateKeywordLoc(SourceLocation TemplateKWLoc) {
*reinterpret_cast<SourceLocation*>
(getTemplateArgs() + NumTemplateArgs) = TemplateKWLoc;
/// \brief Retrieve the template arguments
const TemplateArgumentLoc *getTemplateArgs() const {
return getTrailingObjects<TemplateArgumentLoc>();
}

static const ASTTemplateKWAndArgsInfo*
Create(ASTContext &C, SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo &List);
const TemplateArgumentLoc &operator[](unsigned I) const {
return getTemplateArgs()[I];
}

void initializeFrom(SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo &List);
Expand All @@ -639,6 +644,7 @@ struct ASTTemplateKWAndArgsInfo : public ASTTemplateArgumentListInfo {
bool &ContainsUnexpandedParameterPack);
void initializeFrom(SourceLocation TemplateKWLoc);

void copyInto(TemplateArgumentListInfo &List) const;
static std::size_t sizeFor(unsigned NumTemplateArgs);
};

Expand Down
19 changes: 10 additions & 9 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,8 @@ class CXXNameMangler {
void mangleCXXCtorType(CXXCtorType T);
void mangleCXXDtorType(CXXDtorType T);

void mangleTemplateArgs(const ASTTemplateArgumentListInfo &TemplateArgs);
void mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs);
void mangleTemplateArgs(const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
void mangleTemplateArgs(const TemplateArgumentList &AL);
Expand Down Expand Up @@ -3035,7 +3036,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
ME->isArrow(), ME->getQualifier(), nullptr,
ME->getMemberName(), Arity);
if (ME->hasExplicitTemplateArgs())
mangleTemplateArgs(ME->getExplicitTemplateArgs());
mangleTemplateArgs(ME->getTemplateArgs(), ME->getNumTemplateArgs());
break;
}

Expand All @@ -3047,7 +3048,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
ME->getFirstQualifierFoundInScope(),
ME->getMember(), Arity);
if (ME->hasExplicitTemplateArgs())
mangleTemplateArgs(ME->getExplicitTemplateArgs());
mangleTemplateArgs(ME->getTemplateArgs(), ME->getNumTemplateArgs());
break;
}

Expand All @@ -3059,7 +3060,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
// base-unresolved-name, where <template-args> are just tacked
// onto the end.
if (ULE->hasExplicitTemplateArgs())
mangleTemplateArgs(ULE->getExplicitTemplateArgs());
mangleTemplateArgs(ULE->getTemplateArgs(), ULE->getNumTemplateArgs());
break;
}

Expand Down Expand Up @@ -3381,7 +3382,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
// base-unresolved-name, where <template-args> are just tacked
// onto the end.
if (DRE->hasExplicitTemplateArgs())
mangleTemplateArgs(DRE->getExplicitTemplateArgs());
mangleTemplateArgs(DRE->getTemplateArgs(), DRE->getNumTemplateArgs());
break;
}

Expand Down Expand Up @@ -3649,12 +3650,12 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
}
}

void CXXNameMangler::mangleTemplateArgs(
const ASTTemplateArgumentListInfo &TemplateArgs) {
void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs) {
// <template-args> ::= I <template-arg>+ E
Out << 'I';
for (unsigned i = 0, e = TemplateArgs.NumTemplateArgs; i != e; ++i)
mangleTemplateArg(TemplateArgs.getTemplateArgs()[i].getArgument());
for (unsigned i = 0; i != NumTemplateArgs; ++i)
mangleTemplateArg(TemplateArgs[i].getArgument());
Out << 'E';
}

Expand Down
3 changes: 1 addition & 2 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1275,8 +1275,7 @@ void StmtProfiler::VisitOverloadExpr(const OverloadExpr *S) {
VisitName(S->getName());
ID.AddBoolean(S->hasExplicitTemplateArgs());
if (S->hasExplicitTemplateArgs())
VisitTemplateArguments(S->getExplicitTemplateArgs().getTemplateArgs(),
S->getExplicitTemplateArgs().NumTemplateArgs);
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}

void
Expand Down
93 changes: 35 additions & 58 deletions clang/lib/AST/TemplateBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,17 +520,25 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
const ASTTemplateArgumentListInfo *
ASTTemplateArgumentListInfo::Create(ASTContext &C,
const TemplateArgumentListInfo &List) {
assert(llvm::alignOf<ASTTemplateArgumentListInfo>() >=
llvm::alignOf<TemplateArgumentLoc>());
std::size_t size = ASTTemplateArgumentListInfo::sizeFor(List.size());
std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size());
void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>());
ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo();
TAI->initializeFrom(List);
return TAI;
return new (Mem) ASTTemplateArgumentListInfo(List);
}

void ASTTemplateArgumentListInfo::initializeFrom(
const TemplateArgumentListInfo &Info) {
ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
const TemplateArgumentListInfo &Info) {
LAngleLoc = Info.getLAngleLoc();
RAngleLoc = Info.getRAngleLoc();
NumTemplateArgs = Info.size();

TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
for (unsigned i = 0; i != NumTemplateArgs; ++i)
new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
}

void ASTTemplateKWAndArgsInfo::initializeFrom(
SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info) {
this->TemplateKWLoc = TemplateKWLoc;
LAngleLoc = Info.getLAngleLoc();
RAngleLoc = Info.getRAngleLoc();
NumTemplateArgs = Info.size();
Expand All @@ -540,74 +548,43 @@ void ASTTemplateArgumentListInfo::initializeFrom(
new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
}

void ASTTemplateArgumentListInfo::initializeFrom(
const TemplateArgumentListInfo &Info,
bool &Dependent,
bool &InstantiationDependent,
bool &ContainsUnexpandedParameterPack) {
void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
assert(TemplateKWLoc.isValid());
LAngleLoc = SourceLocation();
RAngleLoc = SourceLocation();
this->TemplateKWLoc = TemplateKWLoc;
NumTemplateArgs = 0;
}

void ASTTemplateKWAndArgsInfo::initializeFrom(
SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
bool &Dependent, bool &InstantiationDependent,
bool &ContainsUnexpandedParameterPack) {
this->TemplateKWLoc = TemplateKWLoc;
LAngleLoc = Info.getLAngleLoc();
RAngleLoc = Info.getRAngleLoc();
NumTemplateArgs = Info.size();

TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
for (unsigned i = 0; i != NumTemplateArgs; ++i) {
Dependent = Dependent || Info[i].getArgument().isDependent();
InstantiationDependent = InstantiationDependent ||
InstantiationDependent = InstantiationDependent ||
Info[i].getArgument().isInstantiationDependent();
ContainsUnexpandedParameterPack
= ContainsUnexpandedParameterPack ||
ContainsUnexpandedParameterPack =
ContainsUnexpandedParameterPack ||
Info[i].getArgument().containsUnexpandedParameterPack();

new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
}
}

void ASTTemplateArgumentListInfo::copyInto(
TemplateArgumentListInfo &Info) const {
void ASTTemplateKWAndArgsInfo::copyInto(TemplateArgumentListInfo &Info) const {
Info.setLAngleLoc(LAngleLoc);
Info.setRAngleLoc(RAngleLoc);
for (unsigned I = 0; I != NumTemplateArgs; ++I)
Info.addArgument(getTemplateArgs()[I]);
}

std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) {
return sizeof(ASTTemplateArgumentListInfo) +
sizeof(TemplateArgumentLoc) * NumTemplateArgs;
}

void
ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo &Info) {
Base::initializeFrom(Info);
setTemplateKeywordLoc(TemplateKWLoc);
}

void
ASTTemplateKWAndArgsInfo
::initializeFrom(SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo &Info,
bool &Dependent,
bool &InstantiationDependent,
bool &ContainsUnexpandedParameterPack) {
Base::initializeFrom(Info, Dependent, InstantiationDependent,
ContainsUnexpandedParameterPack);
setTemplateKeywordLoc(TemplateKWLoc);
}

void
ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
// No explicit template arguments, but template keyword loc is valid.
assert(TemplateKWLoc.isValid());
LAngleLoc = SourceLocation();
RAngleLoc = SourceLocation();
NumTemplateArgs = 0;
setTemplateKeywordLoc(TemplateKWLoc);
}

std::size_t
ASTTemplateKWAndArgsInfo::sizeFor(unsigned NumTemplateArgs) {
// Add space for the template keyword location.
// FIXME: There's room for this in the padding before the template args in
// 64-bit builds.
return Base::sizeFor(NumTemplateArgs) + sizeof(SourceLocation);
std::size_t ASTTemplateKWAndArgsInfo::sizeFor(unsigned NumTemplateArgs) {
return totalSizeToAlloc<TemplateArgumentLoc>(NumTemplateArgs);
}
4 changes: 2 additions & 2 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10176,7 +10176,7 @@ class AddressOfFunctionResolver {
}

if (OvlExpr->hasExplicitTemplateArgs())
OvlExpr->getExplicitTemplateArgs().copyInto(OvlExplicitTemplateArgs);
OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs);

if (FindAllFunctionsThatMatchTargetTypeExactly()) {
// C++ [over.over]p4:
Expand Down Expand Up @@ -10576,7 +10576,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
return nullptr;

TemplateArgumentListInfo ExplicitTemplateArgs;
ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs);
TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc());

// Look through all of the overloaded functions, searching for one
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3037,7 +3037,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
// Gather the explicit template arguments, if any.
TemplateArgumentListInfo ExplicitTemplateArgs;
if (Ovl->hasExplicitTemplateArgs())
Ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
Ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs);
QualType Match;
for (UnresolvedSetIterator I = Ovl->decls_begin(),
E = Ovl->decls_end(); I != E; ++I) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Serialization/ASTWriterStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace clang {

void ASTStmtWriter::
AddTemplateKWAndArgsInfo(const ASTTemplateKWAndArgsInfo &Args) {
Writer.AddSourceLocation(Args.getTemplateKeywordLoc(), Record);
Writer.AddSourceLocation(Args.TemplateKWLoc, Record);
Writer.AddSourceLocation(Args.LAngleLoc, Record);
Writer.AddSourceLocation(Args.RAngleLoc, Record);
for (unsigned i=0; i != Args.NumTemplateArgs; ++i)
Expand Down
77 changes: 45 additions & 32 deletions clang/tools/libclang/CIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1755,13 +1755,27 @@ DEF_JOB(StmtVisit, Stmt, StmtVisitKind)
DEF_JOB(MemberExprParts, MemberExpr, MemberExprPartsKind)
DEF_JOB(DeclRefExprParts, DeclRefExpr, DeclRefExprPartsKind)
DEF_JOB(OverloadExprParts, OverloadExpr, OverloadExprPartsKind)
DEF_JOB(ExplicitTemplateArgsVisit, ASTTemplateArgumentListInfo,
ExplicitTemplateArgsVisitKind)
DEF_JOB(SizeOfPackExprParts, SizeOfPackExpr, SizeOfPackExprPartsKind)
DEF_JOB(LambdaExprParts, LambdaExpr, LambdaExprPartsKind)
DEF_JOB(PostChildrenVisit, void, PostChildrenVisitKind)
#undef DEF_JOB

class ExplicitTemplateArgsVisit : public VisitorJob {
public:
ExplicitTemplateArgsVisit(const TemplateArgumentLoc *Begin,
const TemplateArgumentLoc *End, CXCursor parent)
: VisitorJob(parent, VisitorJob::ExplicitTemplateArgsVisitKind, Begin,
End) {}
static bool classof(const VisitorJob *VJ) {
return VJ->getKind() == ExplicitTemplateArgsVisitKind;
}
const TemplateArgumentLoc *begin() const {
return static_cast<const TemplateArgumentLoc *>(data[0]);
}
const TemplateArgumentLoc *end() {
return static_cast<const TemplateArgumentLoc *>(data[1]);
}
};
class DeclVisit : public VisitorJob {
public:
DeclVisit(const Decl *D, CXCursor parent, bool isFirst) :
Expand Down Expand Up @@ -1949,7 +1963,8 @@ class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void> {
private:
void AddDeclarationNameInfo(const Stmt *S);
void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier);
void AddExplicitTemplateArgs(const ASTTemplateArgumentListInfo *A);
void AddExplicitTemplateArgs(const TemplateArgumentLoc *A,
unsigned NumTemplateArgs);
void AddMemberRef(const FieldDecl *D, SourceLocation L);
void AddStmt(const Stmt *S);
void AddDecl(const Decl *D, bool isFirst = true);
Expand Down Expand Up @@ -1979,10 +1994,9 @@ void EnqueueVisitor::AddDecl(const Decl *D, bool isFirst) {
if (D)
WL.push_back(DeclVisit(D, Parent, isFirst));
}
void EnqueueVisitor::
AddExplicitTemplateArgs(const ASTTemplateArgumentListInfo *A) {
if (A)
WL.push_back(ExplicitTemplateArgsVisit(A, Parent));
void EnqueueVisitor::AddExplicitTemplateArgs(const TemplateArgumentLoc *A,
unsigned NumTemplateArgs) {
WL.push_back(ExplicitTemplateArgsVisit(A, A + NumTemplateArgs, Parent));
}
void EnqueueVisitor::AddMemberRef(const FieldDecl *D, SourceLocation L) {
if (D)
Expand Down Expand Up @@ -2247,7 +2261,8 @@ VisitMSDependentExistsStmt(const MSDependentExistsStmt *S) {

void EnqueueVisitor::
VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) {
AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
if (E->hasExplicitTemplateArgs())
AddExplicitTemplateArgs(E->getTemplateArgs(), E->getNumTemplateArgs());
AddDeclarationNameInfo(E);
if (NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc())
AddNestedNameSpecifierLoc(QualifierLoc);
Expand Down Expand Up @@ -2322,14 +2337,14 @@ void EnqueueVisitor::VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
}

void EnqueueVisitor::VisitDeclRefExpr(const DeclRefExpr *DR) {
if (DR->hasExplicitTemplateArgs()) {
AddExplicitTemplateArgs(&DR->getExplicitTemplateArgs());
}
if (DR->hasExplicitTemplateArgs())
AddExplicitTemplateArgs(DR->getTemplateArgs(), DR->getNumTemplateArgs());
WL.push_back(DeclRefExprParts(DR, Parent));
}
void EnqueueVisitor::VisitDependentScopeDeclRefExpr(
const DependentScopeDeclRefExpr *E) {
AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
if (E->hasExplicitTemplateArgs())
AddExplicitTemplateArgs(E->getTemplateArgs(), E->getNumTemplateArgs());
AddDeclarationNameInfo(E);
AddNestedNameSpecifierLoc(E->getQualifierLoc());
}
Expand Down Expand Up @@ -2443,7 +2458,8 @@ void EnqueueVisitor::VisitOffsetOfExpr(const OffsetOfExpr *E) {
AddTypeLoc(E->getTypeSourceInfo());
}
void EnqueueVisitor::VisitOverloadExpr(const OverloadExpr *E) {
AddExplicitTemplateArgs(E->getOptionalExplicitTemplateArgs());
if (E->hasExplicitTemplateArgs())
AddExplicitTemplateArgs(E->getTemplateArgs(), E->getNumTemplateArgs());
WL.push_back(OverloadExprParts(E, Parent));
}
void EnqueueVisitor::VisitUnaryExprOrTypeTraitExpr(
Expand Down Expand Up @@ -2677,12 +2693,9 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
continue;
}
case VisitorJob::ExplicitTemplateArgsVisitKind: {
const ASTTemplateArgumentListInfo *ArgList =
cast<ExplicitTemplateArgsVisit>(&LI)->get();
for (const TemplateArgumentLoc *Arg = ArgList->getTemplateArgs(),
*ArgEnd = Arg + ArgList->NumTemplateArgs;
Arg != ArgEnd; ++Arg) {
if (VisitTemplateArgumentLoc(*Arg))
for (const TemplateArgumentLoc &Arg :
*cast<ExplicitTemplateArgsVisit>(&LI)) {
if (VisitTemplateArgumentLoc(Arg))
return true;
}
continue;
Expand Down Expand Up @@ -2884,10 +2897,9 @@ bool CursorVisitor::Visit(const Stmt *S) {

namespace {
typedef SmallVector<SourceRange, 4> RefNamePieces;
RefNamePieces
buildPieces(unsigned NameFlags, bool IsMemberRefExpr,
const DeclarationNameInfo &NI, SourceRange QLoc,
const ASTTemplateArgumentListInfo *TemplateArgs = nullptr) {
RefNamePieces buildPieces(unsigned NameFlags, bool IsMemberRefExpr,
const DeclarationNameInfo &NI, SourceRange QLoc,
const SourceRange *TemplateArgsLoc = nullptr) {
const bool WantQualifier = NameFlags & CXNameRange_WantQualifier;
const bool WantTemplateArgs = NameFlags & CXNameRange_WantTemplateArgs;
const bool WantSinglePiece = NameFlags & CXNameRange_WantSinglePiece;
Expand All @@ -2901,11 +2913,10 @@ buildPieces(unsigned NameFlags, bool IsMemberRefExpr,

if (Kind != DeclarationName::CXXOperatorName || IsMemberRefExpr)
Pieces.push_back(NI.getLoc());

if (WantTemplateArgs && TemplateArgs)
Pieces.push_back(SourceRange(TemplateArgs->LAngleLoc,
TemplateArgs->RAngleLoc));


if (WantTemplateArgs && TemplateArgsLoc && TemplateArgsLoc->isValid())
Pieces.push_back(*TemplateArgsLoc);

if (Kind == DeclarationName::CXXOperatorName) {
Pieces.push_back(SourceLocation::getFromRawEncoding(
NI.getInfo().CXXOperatorName.BeginOpNameLoc));
Expand Down Expand Up @@ -5524,10 +5535,12 @@ CXSourceRange clang_getCursorReferenceNameRange(CXCursor C, unsigned NameFlags,
break;

case CXCursor_DeclRefExpr:
if (const DeclRefExpr *E = dyn_cast<DeclRefExpr>(getCursorExpr(C)))
Pieces = buildPieces(NameFlags, false, E->getNameInfo(),
E->getQualifierLoc().getSourceRange(),
E->getOptionalExplicitTemplateArgs());
if (const DeclRefExpr *E = dyn_cast<DeclRefExpr>(getCursorExpr(C))) {
SourceRange TemplateArgLoc(E->getLAngleLoc(), E->getRAngleLoc());
Pieces =
buildPieces(NameFlags, false, E->getNameInfo(),
E->getQualifierLoc().getSourceRange(), &TemplateArgLoc);
}
break;

case CXCursor_CallExpr:
Expand Down