[cfe-commits] r66572 - in /cfe/trunk: include/clang/AST/Type.h include/clang/Basic/DiagnosticSemaKinds.def include/clang/Frontend/TextDiagnosticPrinter.h lib/AST/Type.cpp lib/Frontend/TextDiagnosticPrinter.cpp lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp test/SemaTemplate/instantiation-default-1.cpp test/SemaTemplate/instantiation-default-2.cpp
Douglas Gregor
dgregor at apple.com
Tue Mar 10 13:44:00 PDT 2009
Author: dgregor
Date: Tue Mar 10 15:44:00 2009
New Revision: 66572
URL: http://llvm.org/viewvc/llvm-project?rev=66572&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
cfe/trunk/include/clang/Frontend/TextDiagnosticPrinter.h
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp
cfe/trunk/test/SemaTemplate/instantiation-default-2.cpp
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=66572&r1=66571&r2=66572&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Tue Mar 10 15:44:00 2009
@@ -1449,6 +1449,11 @@
static bool anyDependentTemplateArguments(const TemplateArgument *Args,
unsigned NumArgs);
+ /// \brief Print a template argument list, including the '<' and '>'
+ /// enclosing the template arguments.
+ static std::string PrintTemplateArgumentList(const TemplateArgument *Args,
+ unsigned NumArgs);
+
typedef const TemplateArgument * iterator;
iterator begin() const { return getArgs(); }
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=66572&r1=66571&r2=66572&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Tue Mar 10 15:44:00 2009
@@ -649,6 +649,8 @@
"implicit instantiation of undefined template %0")
DIAG(note_template_class_instantiation_here, NOTE,
"in instantiation of template class %0 requested here")
+DIAG(note_default_arg_instantiation_here, NOTE,
+ "in instantiation of default argument for '%0' required here")
DIAG(err_unexpected_typedef, ERROR,
"unexpected type name %0: expected expression")
Modified: cfe/trunk/include/clang/Frontend/TextDiagnosticPrinter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/TextDiagnosticPrinter.h?rev=66572&r1=66571&r2=66572&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/TextDiagnosticPrinter.h (original)
+++ cfe/trunk/include/clang/Frontend/TextDiagnosticPrinter.h Tue Mar 10 15:44:00 2009
@@ -28,6 +28,7 @@
class TextDiagnosticPrinter : public DiagnosticClient {
SourceLocation LastWarningLoc;
FullSourceLoc LastLoc;
+ bool LastCaretDiagnosticWasNote;
llvm::raw_ostream &OS;
bool ShowColumn;
bool CaretDiagnostics;
@@ -35,8 +36,8 @@
public:
TextDiagnosticPrinter(llvm::raw_ostream &os, bool showColumn = true,
bool caretDiagnistics = true, bool showLocation = true)
- : OS(os), ShowColumn(showColumn), CaretDiagnostics(caretDiagnistics),
- ShowLocation(showLocation) {}
+ : LastCaretDiagnosticWasNote(false), OS(os), ShowColumn(showColumn),
+ CaretDiagnostics(caretDiagnistics), ShowLocation(showLocation) {}
void PrintIncludeStack(SourceLocation Loc, const SourceManager &SM);
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=66572&r1=66571&r2=66572&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Tue Mar 10 15:44:00 2009
@@ -1287,10 +1287,9 @@
InnerString = Name->getName() + InnerString;
}
-/// \brief Print a template argument list, including the '<' and '>'
-/// enclosing the template arguments.
-static std::string printTemplateArgumentList(const TemplateArgument *Args,
- unsigned NumArgs) {
+std::string ClassTemplateSpecializationType::PrintTemplateArgumentList(
+ const TemplateArgument *Args,
+ unsigned NumArgs) {
std::string SpecString;
SpecString += '<';
for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
@@ -1343,7 +1342,7 @@
ClassTemplateSpecializationType::
getAsStringInternal(std::string &InnerString) const {
std::string SpecString = Template->getNameAsString();
- SpecString += printTemplateArgumentList(getArgs(), getNumArgs());
+ SpecString += PrintTemplateArgumentList(getArgs(), getNumArgs());
if (InnerString.empty())
InnerString.swap(SpecString);
else
@@ -1409,8 +1408,9 @@
if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(getDecl())) {
std::string TemplateArgs
- = printTemplateArgumentList(Spec->getTemplateArgs(),
- Spec->getNumTemplateArgs());
+ = ClassTemplateSpecializationType::PrintTemplateArgumentList(
+ Spec->getTemplateArgs(),
+ Spec->getNumTemplateArgs());
InnerString = TemplateArgs + InnerString;
}
Modified: cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp?rev=66572&r1=66571&r2=66572&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp (original)
+++ cfe/trunk/lib/Frontend/TextDiagnosticPrinter.cpp Tue Mar 10 15:44:00 2009
@@ -278,15 +278,19 @@
OS.write(OutStr.begin(), OutStr.size());
OS << '\n';
- // If caret diagnostics are enabled and we have location, we want to emit the
- // caret. However, we only do this if the location moved from the last
- // diagnostic, or if the diagnostic has ranges. We don't want to emit the
- // same caret multiple times if one loc has multiple diagnostics.
+ // If caret diagnostics are enabled and we have location, we want to
+ // emit the caret. However, we only do this if the location moved
+ // from the last diagnostic, if the last diagnostic was a note that
+ // was part of a different warning or error diagnostic, or if the
+ // diagnostic has ranges. We don't want to emit the same caret
+ // multiple times if one loc has multiple diagnostics.
if (CaretDiagnostics && Info.getLocation().isValid() &&
((LastLoc != Info.getLocation()) || Info.getNumRanges() ||
+ (LastCaretDiagnosticWasNote && Level != Diagnostic::Note) ||
Info.getNumCodeModificationHints())) {
// Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
LastLoc = Info.getLocation();
+ LastCaretDiagnosticWasNote = (Level == Diagnostic::Note);
// Get the ranges into a local array we can hack on.
SourceRange Ranges[20];
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=66572&r1=66571&r2=66572&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Mar 10 15:44:00 2009
@@ -245,7 +245,7 @@
DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
if (!Diags.isBuiltinNote(DiagID) &&
!ActiveTemplateInstantiations.empty() &&
- ActiveTemplateInstantiations.back().Entity
+ ActiveTemplateInstantiations.back()
!= LastTemplateInstantiationErrorContext)
DB << PostDiagnosticHook(PrintInstantiationStackHook, this);
return DB;
@@ -1673,16 +1673,61 @@
/// \brief A template instantiation that is currently in progress.
struct ActiveTemplateInstantiation {
+ /// \brief The kind of template instantiation we are performing
+ enum {
+ /// We are instantiating a template declaration. The entity is
+ /// the declaration we're instantiation (e.g., a
+ /// ClassTemplateSpecializationDecl).
+ TemplateInstantiation,
+
+ /// We are instantiating a default argument for a template
+ /// parameter. The Entity is the template, and
+ /// TemplateArgs/NumTemplateArguments provides the template
+ /// arguments as specified.
+ DefaultTemplateArgumentInstantiation
+ } Kind;
+
/// \brief The point of instantiation within the source code.
SourceLocation PointOfInstantiation;
/// \brief The entity that is being instantiated.
- ClassTemplateSpecializationDecl *Entity;
+ uintptr_t Entity;
+
+ // \brief If this the instantiation of a default template
+ // argument, the list of tempalte arguments.
+ const TemplateArgument *TemplateArgs;
+
+ /// \brief The number of template arguments in TemplateArgs.
+ unsigned NumTemplateArgs;
/// \brief The source range that covers the construct that cause
/// the instantiation, e.g., the template-id that causes a class
/// template instantiation.
SourceRange InstantiationRange;
+
+ friend bool operator==(const ActiveTemplateInstantiation &X,
+ const ActiveTemplateInstantiation &Y) {
+ if (X.Kind != Y.Kind)
+ return false;
+
+ if (X.Entity != Y.Entity)
+ return false;
+
+ switch (X.Kind) {
+ case TemplateInstantiation:
+ return true;
+
+ case DefaultTemplateArgumentInstantiation:
+ return X.TemplateArgs == Y.TemplateArgs;
+ }
+
+ return true;
+ }
+
+ friend bool operator!=(const ActiveTemplateInstantiation &X,
+ const ActiveTemplateInstantiation &Y) {
+ return !(X == Y);
+ }
};
/// \brief List of active template instantiations.
@@ -1701,7 +1746,7 @@
/// instantiation backtraces when there are multiple errors in the
/// same instantiation. FIXME: Does this belong in Sema? It's tough
/// to implement it anywhere else.
- ClassTemplateSpecializationDecl *LastTemplateInstantiationErrorContext;
+ ActiveTemplateInstantiation LastTemplateInstantiationErrorContext;
/// \brief A stack object to be created when performing template
/// instantiation.
@@ -1715,9 +1760,19 @@
/// Destruction of this object will pop the named instantiation off
/// the stack.
struct InstantiatingTemplate {
+ /// \brief Note that we are instantiating a class template.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *Entity,
SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are instantiating a default argument in a
+ /// template-id.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange = SourceRange());
+
~InstantiatingTemplate();
/// \brief Determines whether we have exceeded the maximum
@@ -1728,6 +1783,9 @@
Sema &SemaRef;
bool Invalid;
+ bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
+ SourceRange InstantiationRange);
+
InstantiatingTemplate(const InstantiatingTemplate&); // not implemented
InstantiatingTemplate&
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=66572&r1=66571&r2=66572&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Mar 10 15:44:00 2009
@@ -825,10 +825,15 @@
// If the argument type is dependent, instantiate it now based
// on the previously-computed template arguments.
- if (ArgType->isDependentType())
+ if (ArgType->isDependentType()) {
+ InstantiatingTemplate Inst(*this, TemplateLoc,
+ Template, &Converted[0],
+ Converted.size(),
+ SourceRange(TemplateLoc, RAngleLoc));
ArgType = InstantiateType(ArgType, &Converted[0], Converted.size(),
TTP->getDefaultArgumentLoc(),
TTP->getDeclName());
+ }
if (ArgType.isNull())
return true;
@@ -888,6 +893,11 @@
QualType NTTPType = NTTP->getType();
if (NTTPType->isDependentType()) {
// Instantiate the type of the non-type template parameter.
+ InstantiatingTemplate Inst(*this, TemplateLoc,
+ Template, &Converted[0],
+ Converted.size(),
+ SourceRange(TemplateLoc, RAngleLoc));
+
NTTPType = InstantiateType(NTTPType,
&Converted[0], Converted.size(),
NTTP->getLocation(),
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=66572&r1=66571&r2=66572&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Mar 10 15:44:00 2009
@@ -30,19 +30,38 @@
ClassTemplateSpecializationDecl *Entity,
SourceRange InstantiationRange)
: SemaRef(SemaRef) {
- if (SemaRef.ActiveTemplateInstantiations.size()
- > SemaRef.getLangOptions().InstantiationDepth) {
- SemaRef.Diag(PointOfInstantiation,
- diag::err_template_recursion_depth_exceeded)
- << SemaRef.getLangOptions().InstantiationDepth
- << InstantiationRange;
- SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
- << SemaRef.getLangOptions().InstantiationDepth;
- Invalid = true;
- } else {
+
+ Invalid = CheckInstantiationDepth(PointOfInstantiation,
+ InstantiationRange);
+ if (!Invalid) {
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+ Invalid = false;
+ }
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+ SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceRange InstantiationRange)
+ : SemaRef(SemaRef) {
+
+ Invalid = CheckInstantiationDepth(PointOfInstantiation,
+ InstantiationRange);
+ if (!Invalid) {
ActiveTemplateInstantiation Inst;
+ Inst.Kind
+ = ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation;
Inst.PointOfInstantiation = PointOfInstantiation;
- Inst.Entity = Entity;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Template);
+ Inst.TemplateArgs = TemplateArgs;
+ Inst.NumTemplateArgs = NumTemplateArgs;
Inst.InstantiationRange = InstantiationRange;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
Invalid = false;
@@ -54,12 +73,28 @@
SemaRef.ActiveTemplateInstantiations.pop_back();
}
+bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
+ SourceLocation PointOfInstantiation,
+ SourceRange InstantiationRange) {
+ if (SemaRef.ActiveTemplateInstantiations.size()
+ <= SemaRef.getLangOptions().InstantiationDepth)
+ return false;
+
+ SemaRef.Diag(PointOfInstantiation,
+ diag::err_template_recursion_depth_exceeded)
+ << SemaRef.getLangOptions().InstantiationDepth
+ << InstantiationRange;
+ SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
+ << SemaRef.getLangOptions().InstantiationDepth;
+ return true;
+}
+
/// \brief Post-diagnostic hook for printing the instantiation stack.
void Sema::PrintInstantiationStackHook(unsigned, void *Cookie) {
Sema &SemaRef = *static_cast<Sema*>(Cookie);
SemaRef.PrintInstantiationStack();
SemaRef.LastTemplateInstantiationErrorContext
- = SemaRef.ActiveTemplateInstantiations.back().Entity;
+ = SemaRef.ActiveTemplateInstantiations.back();
}
/// \brief Prints the current instantiation stack through a series of
@@ -70,10 +105,30 @@
ActiveEnd = ActiveTemplateInstantiations.rend();
Active != ActiveEnd;
++Active) {
- Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
- diag::note_template_class_instantiation_here)
- << Context.getTypeDeclType(Active->Entity)
- << Active->InstantiationRange;
+ switch (Active->Kind) {
+ case ActiveTemplateInstantiation::TemplateInstantiation: {
+ ClassTemplateSpecializationDecl *Spec
+ = cast<ClassTemplateSpecializationDecl>((Decl*)Active->Entity);
+ Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+ diag::note_template_class_instantiation_here)
+ << Context.getTypeDeclType(Spec)
+ << Active->InstantiationRange;
+ break;
+ }
+
+ case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
+ TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity);
+ std::string TemplateArgsStr
+ = ClassTemplateSpecializationType::PrintTemplateArgumentList(
+ Active->TemplateArgs,
+ Active->NumTemplateArgs);
+ Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+ diag::note_default_arg_instantiation_here)
+ << (Template->getNameAsString() + TemplateArgsStr)
+ << Active->InstantiationRange;
+ break;
+ }
+ }
}
}
@@ -482,6 +537,10 @@
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
SourceLocation Loc, DeclarationName Entity) {
+ assert(!ActiveTemplateInstantiations.empty() &&
+ "Cannot perform an instantiation without some context on the "
+ "instantiation stack");
+
// If T is not a dependent type, there is nothing to do.
if (!T->isDependentType())
return T;
Modified: cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp?rev=66572&r1=66571&r2=66572&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiation-default-1.cpp Tue Mar 10 15:44:00 2009
@@ -32,7 +32,8 @@
d2->foo();
}
-Def2<int&> *d2;
+typedef int& int_ref_t;
+Def2<int_ref_t> *d2; // expected-note{{in instantiation of default argument for 'Def2<int &>' required here}}
template<> struct Def1<const int, const int> { }; // expected-error{{redefinition of 'Def1'}}
Modified: cfe/trunk/test/SemaTemplate/instantiation-default-2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiation-default-2.cpp?rev=66572&r1=66571&r2=66572&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiation-default-2.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiation-default-2.cpp Tue Mar 10 15:44:00 2009
@@ -15,4 +15,4 @@
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)'}}
-Constant<float, 0> *c7;
+Constant<float, 0> *c7; // expected-note{{in instantiation of default argument for 'Constant<float>' required here}}
More information about the cfe-commits
mailing list