Skip to content

Commit 79cf603

Browse files
committed
Extend the notion of active template instantiations to include the
context of a template-id for which we need to instantiate default template arguments. In the TextDiagnosticPrinter, don't suppress the caret diagnostic if we are producing a non-note diagnostic that follows a note diagnostic with the same location, because notes are (conceptually) a part of the warning or error that comes before them. llvm-svn: 66572
1 parent e8dd284 commit 79cf603

File tree

10 files changed

+175
-35
lines changed

10 files changed

+175
-35
lines changed

clang/include/clang/AST/Type.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,11 @@ class ClassTemplateSpecializationType
14491449
static bool anyDependentTemplateArguments(const TemplateArgument *Args,
14501450
unsigned NumArgs);
14511451

1452+
/// \brief Print a template argument list, including the '<' and '>'
1453+
/// enclosing the template arguments.
1454+
static std::string PrintTemplateArgumentList(const TemplateArgument *Args,
1455+
unsigned NumArgs);
1456+
14521457
typedef const TemplateArgument * iterator;
14531458

14541459
iterator begin() const { return getArgs(); }

clang/include/clang/Basic/DiagnosticSemaKinds.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,8 @@ DIAG(err_template_implicit_instantiate_undefined, ERROR,
649649
"implicit instantiation of undefined template %0")
650650
DIAG(note_template_class_instantiation_here, NOTE,
651651
"in instantiation of template class %0 requested here")
652+
DIAG(note_default_arg_instantiation_here, NOTE,
653+
"in instantiation of default argument for '%0' required here")
652654

653655
DIAG(err_unexpected_typedef, ERROR,
654656
"unexpected type name %0: expected expression")

clang/include/clang/Frontend/TextDiagnosticPrinter.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,16 @@ class SourceManager;
2828
class TextDiagnosticPrinter : public DiagnosticClient {
2929
SourceLocation LastWarningLoc;
3030
FullSourceLoc LastLoc;
31+
bool LastCaretDiagnosticWasNote;
3132
llvm::raw_ostream &OS;
3233
bool ShowColumn;
3334
bool CaretDiagnostics;
3435
bool ShowLocation;
3536
public:
3637
TextDiagnosticPrinter(llvm::raw_ostream &os, bool showColumn = true,
3738
bool caretDiagnistics = true, bool showLocation = true)
38-
: OS(os), ShowColumn(showColumn), CaretDiagnostics(caretDiagnistics),
39-
ShowLocation(showLocation) {}
39+
: LastCaretDiagnosticWasNote(false), OS(os), ShowColumn(showColumn),
40+
CaretDiagnostics(caretDiagnistics), ShowLocation(showLocation) {}
4041

4142
void PrintIncludeStack(SourceLocation Loc, const SourceManager &SM);
4243

clang/lib/AST/Type.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,10 +1287,9 @@ void TemplateTypeParmType::getAsStringInternal(std::string &InnerString) const {
12871287
InnerString = Name->getName() + InnerString;
12881288
}
12891289

1290-
/// \brief Print a template argument list, including the '<' and '>'
1291-
/// enclosing the template arguments.
1292-
static std::string printTemplateArgumentList(const TemplateArgument *Args,
1293-
unsigned NumArgs) {
1290+
std::string ClassTemplateSpecializationType::PrintTemplateArgumentList(
1291+
const TemplateArgument *Args,
1292+
unsigned NumArgs) {
12941293
std::string SpecString;
12951294
SpecString += '<';
12961295
for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
@@ -1343,7 +1342,7 @@ void
13431342
ClassTemplateSpecializationType::
13441343
getAsStringInternal(std::string &InnerString) const {
13451344
std::string SpecString = Template->getNameAsString();
1346-
SpecString += printTemplateArgumentList(getArgs(), getNumArgs());
1345+
SpecString += PrintTemplateArgumentList(getArgs(), getNumArgs());
13471346
if (InnerString.empty())
13481347
InnerString.swap(SpecString);
13491348
else
@@ -1409,8 +1408,9 @@ void TagType::getAsStringInternal(std::string &InnerString) const {
14091408
if (ClassTemplateSpecializationDecl *Spec
14101409
= dyn_cast<ClassTemplateSpecializationDecl>(getDecl())) {
14111410
std::string TemplateArgs
1412-
= printTemplateArgumentList(Spec->getTemplateArgs(),
1413-
Spec->getNumTemplateArgs());
1411+
= ClassTemplateSpecializationType::PrintTemplateArgumentList(
1412+
Spec->getTemplateArgs(),
1413+
Spec->getNumTemplateArgs());
14141414
InnerString = TemplateArgs + InnerString;
14151415
}
14161416

clang/lib/Frontend/TextDiagnosticPrinter.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,15 +278,19 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
278278
OS.write(OutStr.begin(), OutStr.size());
279279
OS << '\n';
280280

281-
// If caret diagnostics are enabled and we have location, we want to emit the
282-
// caret. However, we only do this if the location moved from the last
283-
// diagnostic, or if the diagnostic has ranges. We don't want to emit the
284-
// same caret multiple times if one loc has multiple diagnostics.
281+
// If caret diagnostics are enabled and we have location, we want to
282+
// emit the caret. However, we only do this if the location moved
283+
// from the last diagnostic, if the last diagnostic was a note that
284+
// was part of a different warning or error diagnostic, or if the
285+
// diagnostic has ranges. We don't want to emit the same caret
286+
// multiple times if one loc has multiple diagnostics.
285287
if (CaretDiagnostics && Info.getLocation().isValid() &&
286288
((LastLoc != Info.getLocation()) || Info.getNumRanges() ||
289+
(LastCaretDiagnosticWasNote && Level != Diagnostic::Note) ||
287290
Info.getNumCodeModificationHints())) {
288291
// Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
289292
LastLoc = Info.getLocation();
293+
LastCaretDiagnosticWasNote = (Level == Diagnostic::Note);
290294

291295
// Get the ranges into a local array we can hack on.
292296
SourceRange Ranges[20];

clang/lib/Sema/Sema.h

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ class Sema : public Action {
245245
DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
246246
if (!Diags.isBuiltinNote(DiagID) &&
247247
!ActiveTemplateInstantiations.empty() &&
248-
ActiveTemplateInstantiations.back().Entity
248+
ActiveTemplateInstantiations.back()
249249
!= LastTemplateInstantiationErrorContext)
250250
DB << PostDiagnosticHook(PrintInstantiationStackHook, this);
251251
return DB;
@@ -1673,16 +1673,61 @@ class Sema : public Action {
16731673

16741674
/// \brief A template instantiation that is currently in progress.
16751675
struct ActiveTemplateInstantiation {
1676+
/// \brief The kind of template instantiation we are performing
1677+
enum {
1678+
/// We are instantiating a template declaration. The entity is
1679+
/// the declaration we're instantiation (e.g., a
1680+
/// ClassTemplateSpecializationDecl).
1681+
TemplateInstantiation,
1682+
1683+
/// We are instantiating a default argument for a template
1684+
/// parameter. The Entity is the template, and
1685+
/// TemplateArgs/NumTemplateArguments provides the template
1686+
/// arguments as specified.
1687+
DefaultTemplateArgumentInstantiation
1688+
} Kind;
1689+
16761690
/// \brief The point of instantiation within the source code.
16771691
SourceLocation PointOfInstantiation;
16781692

16791693
/// \brief The entity that is being instantiated.
1680-
ClassTemplateSpecializationDecl *Entity;
1694+
uintptr_t Entity;
1695+
1696+
// \brief If this the instantiation of a default template
1697+
// argument, the list of tempalte arguments.
1698+
const TemplateArgument *TemplateArgs;
1699+
1700+
/// \brief The number of template arguments in TemplateArgs.
1701+
unsigned NumTemplateArgs;
16811702

16821703
/// \brief The source range that covers the construct that cause
16831704
/// the instantiation, e.g., the template-id that causes a class
16841705
/// template instantiation.
16851706
SourceRange InstantiationRange;
1707+
1708+
friend bool operator==(const ActiveTemplateInstantiation &X,
1709+
const ActiveTemplateInstantiation &Y) {
1710+
if (X.Kind != Y.Kind)
1711+
return false;
1712+
1713+
if (X.Entity != Y.Entity)
1714+
return false;
1715+
1716+
switch (X.Kind) {
1717+
case TemplateInstantiation:
1718+
return true;
1719+
1720+
case DefaultTemplateArgumentInstantiation:
1721+
return X.TemplateArgs == Y.TemplateArgs;
1722+
}
1723+
1724+
return true;
1725+
}
1726+
1727+
friend bool operator!=(const ActiveTemplateInstantiation &X,
1728+
const ActiveTemplateInstantiation &Y) {
1729+
return !(X == Y);
1730+
}
16861731
};
16871732

16881733
/// \brief List of active template instantiations.
@@ -1701,7 +1746,7 @@ class Sema : public Action {
17011746
/// instantiation backtraces when there are multiple errors in the
17021747
/// same instantiation. FIXME: Does this belong in Sema? It's tough
17031748
/// to implement it anywhere else.
1704-
ClassTemplateSpecializationDecl *LastTemplateInstantiationErrorContext;
1749+
ActiveTemplateInstantiation LastTemplateInstantiationErrorContext;
17051750

17061751
/// \brief A stack object to be created when performing template
17071752
/// instantiation.
@@ -1715,9 +1760,19 @@ class Sema : public Action {
17151760
/// Destruction of this object will pop the named instantiation off
17161761
/// the stack.
17171762
struct InstantiatingTemplate {
1763+
/// \brief Note that we are instantiating a class template.
17181764
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
17191765
ClassTemplateSpecializationDecl *Entity,
17201766
SourceRange InstantiationRange = SourceRange());
1767+
1768+
/// \brief Note that we are instantiating a default argument in a
1769+
/// template-id.
1770+
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
1771+
TemplateDecl *Template,
1772+
const TemplateArgument *TemplateArgs,
1773+
unsigned NumTemplateArgs,
1774+
SourceRange InstantiationRange = SourceRange());
1775+
17211776
~InstantiatingTemplate();
17221777

17231778
/// \brief Determines whether we have exceeded the maximum
@@ -1728,6 +1783,9 @@ class Sema : public Action {
17281783
Sema &SemaRef;
17291784
bool Invalid;
17301785

1786+
bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
1787+
SourceRange InstantiationRange);
1788+
17311789
InstantiatingTemplate(const InstantiatingTemplate&); // not implemented
17321790

17331791
InstantiatingTemplate&

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -825,10 +825,15 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
825825

826826
// If the argument type is dependent, instantiate it now based
827827
// on the previously-computed template arguments.
828-
if (ArgType->isDependentType())
828+
if (ArgType->isDependentType()) {
829+
InstantiatingTemplate Inst(*this, TemplateLoc,
830+
Template, &Converted[0],
831+
Converted.size(),
832+
SourceRange(TemplateLoc, RAngleLoc));
829833
ArgType = InstantiateType(ArgType, &Converted[0], Converted.size(),
830834
TTP->getDefaultArgumentLoc(),
831835
TTP->getDeclName());
836+
}
832837

833838
if (ArgType.isNull())
834839
return true;
@@ -888,6 +893,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
888893
QualType NTTPType = NTTP->getType();
889894
if (NTTPType->isDependentType()) {
890895
// Instantiate the type of the non-type template parameter.
896+
InstantiatingTemplate Inst(*this, TemplateLoc,
897+
Template, &Converted[0],
898+
Converted.size(),
899+
SourceRange(TemplateLoc, RAngleLoc));
900+
891901
NTTPType = InstantiateType(NTTPType,
892902
&Converted[0], Converted.size(),
893903
NTTP->getLocation(),

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 75 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,38 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
3030
ClassTemplateSpecializationDecl *Entity,
3131
SourceRange InstantiationRange)
3232
: SemaRef(SemaRef) {
33-
if (SemaRef.ActiveTemplateInstantiations.size()
34-
> SemaRef.getLangOptions().InstantiationDepth) {
35-
SemaRef.Diag(PointOfInstantiation,
36-
diag::err_template_recursion_depth_exceeded)
37-
<< SemaRef.getLangOptions().InstantiationDepth
38-
<< InstantiationRange;
39-
SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
40-
<< SemaRef.getLangOptions().InstantiationDepth;
41-
Invalid = true;
42-
} else {
33+
34+
Invalid = CheckInstantiationDepth(PointOfInstantiation,
35+
InstantiationRange);
36+
if (!Invalid) {
37+
ActiveTemplateInstantiation Inst;
38+
Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation;
39+
Inst.PointOfInstantiation = PointOfInstantiation;
40+
Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
41+
Inst.InstantiationRange = InstantiationRange;
42+
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
43+
Invalid = false;
44+
}
45+
}
46+
47+
Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
48+
SourceLocation PointOfInstantiation,
49+
TemplateDecl *Template,
50+
const TemplateArgument *TemplateArgs,
51+
unsigned NumTemplateArgs,
52+
SourceRange InstantiationRange)
53+
: SemaRef(SemaRef) {
54+
55+
Invalid = CheckInstantiationDepth(PointOfInstantiation,
56+
InstantiationRange);
57+
if (!Invalid) {
4358
ActiveTemplateInstantiation Inst;
59+
Inst.Kind
60+
= ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation;
4461
Inst.PointOfInstantiation = PointOfInstantiation;
45-
Inst.Entity = Entity;
62+
Inst.Entity = reinterpret_cast<uintptr_t>(Template);
63+
Inst.TemplateArgs = TemplateArgs;
64+
Inst.NumTemplateArgs = NumTemplateArgs;
4665
Inst.InstantiationRange = InstantiationRange;
4766
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
4867
Invalid = false;
@@ -54,12 +73,28 @@ Sema::InstantiatingTemplate::~InstantiatingTemplate() {
5473
SemaRef.ActiveTemplateInstantiations.pop_back();
5574
}
5675

76+
bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
77+
SourceLocation PointOfInstantiation,
78+
SourceRange InstantiationRange) {
79+
if (SemaRef.ActiveTemplateInstantiations.size()
80+
<= SemaRef.getLangOptions().InstantiationDepth)
81+
return false;
82+
83+
SemaRef.Diag(PointOfInstantiation,
84+
diag::err_template_recursion_depth_exceeded)
85+
<< SemaRef.getLangOptions().InstantiationDepth
86+
<< InstantiationRange;
87+
SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
88+
<< SemaRef.getLangOptions().InstantiationDepth;
89+
return true;
90+
}
91+
5792
/// \brief Post-diagnostic hook for printing the instantiation stack.
5893
void Sema::PrintInstantiationStackHook(unsigned, void *Cookie) {
5994
Sema &SemaRef = *static_cast<Sema*>(Cookie);
6095
SemaRef.PrintInstantiationStack();
6196
SemaRef.LastTemplateInstantiationErrorContext
62-
= SemaRef.ActiveTemplateInstantiations.back().Entity;
97+
= SemaRef.ActiveTemplateInstantiations.back();
6398
}
6499

65100
/// \brief Prints the current instantiation stack through a series of
@@ -70,10 +105,30 @@ void Sema::PrintInstantiationStack() {
70105
ActiveEnd = ActiveTemplateInstantiations.rend();
71106
Active != ActiveEnd;
72107
++Active) {
73-
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
74-
diag::note_template_class_instantiation_here)
75-
<< Context.getTypeDeclType(Active->Entity)
76-
<< Active->InstantiationRange;
108+
switch (Active->Kind) {
109+
case ActiveTemplateInstantiation::TemplateInstantiation: {
110+
ClassTemplateSpecializationDecl *Spec
111+
= cast<ClassTemplateSpecializationDecl>((Decl*)Active->Entity);
112+
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
113+
diag::note_template_class_instantiation_here)
114+
<< Context.getTypeDeclType(Spec)
115+
<< Active->InstantiationRange;
116+
break;
117+
}
118+
119+
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
120+
TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity);
121+
std::string TemplateArgsStr
122+
= ClassTemplateSpecializationType::PrintTemplateArgumentList(
123+
Active->TemplateArgs,
124+
Active->NumTemplateArgs);
125+
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
126+
diag::note_default_arg_instantiation_here)
127+
<< (Template->getNameAsString() + TemplateArgsStr)
128+
<< Active->InstantiationRange;
129+
break;
130+
}
131+
}
77132
}
78133
}
79134

@@ -482,6 +537,10 @@ QualType Sema::InstantiateType(QualType T,
482537
const TemplateArgument *TemplateArgs,
483538
unsigned NumTemplateArgs,
484539
SourceLocation Loc, DeclarationName Entity) {
540+
assert(!ActiveTemplateInstantiations.empty() &&
541+
"Cannot perform an instantiation without some context on the "
542+
"instantiation stack");
543+
485544
// If T is not a dependent type, there is nothing to do.
486545
if (!T->isDependentType())
487546
return T;

clang/test/SemaTemplate/instantiation-default-1.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ void test_Def2(Def2<int, int const*> *d2) {
3232
d2->foo();
3333
}
3434

35-
Def2<int&> *d2;
35+
typedef int& int_ref_t;
36+
Def2<int_ref_t> *d2; // expected-note{{in instantiation of default argument for 'Def2<int &>' required here}}
3637

3738

3839
template<> struct Def1<const int, const int> { }; // expected-error{{redefinition of 'Def1'}}

clang/test/SemaTemplate/instantiation-default-2.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ Constant<float (*)(int, double), &f> *c5;
1515

1616
Constant<float (*)(int, int), f> *c6; // expected-error{{non-type template argument of type 'float (*)(int, double)' cannot be converted to a value of type 'float (*)(int, int)'}}
1717

18-
Constant<float, 0> *c7;
18+
Constant<float, 0> *c7; // expected-note{{in instantiation of default argument for 'Constant<float>' required here}}

0 commit comments

Comments
 (0)