зеркало из https://github.com/microsoft/clang-1.git
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66572 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
27b152fa74
Коммит
df667e71b1
|
@ -1449,6 +1449,11 @@ public:
|
|||
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(); }
|
||||
|
|
|
@ -649,6 +649,8 @@ DIAG(err_template_implicit_instantiate_undefined, ERROR,
|
|||
"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")
|
||||
|
|
|
@ -28,6 +28,7 @@ class SourceManager;
|
|||
class TextDiagnosticPrinter : public DiagnosticClient {
|
||||
SourceLocation LastWarningLoc;
|
||||
FullSourceLoc LastLoc;
|
||||
bool LastCaretDiagnosticWasNote;
|
||||
llvm::raw_ostream &OS;
|
||||
bool ShowColumn;
|
||||
bool CaretDiagnostics;
|
||||
|
@ -35,8 +36,8 @@ class TextDiagnosticPrinter : public DiagnosticClient {
|
|||
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);
|
||||
|
||||
|
|
|
@ -1287,10 +1287,9 @@ void TemplateTypeParmType::getAsStringInternal(std::string &InnerString) const {
|
|||
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 @@ void
|
|||
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 @@ void TagType::getAsStringInternal(std::string &InnerString) const {
|
|||
if (ClassTemplateSpecializationDecl *Spec
|
||||
= dyn_cast<ClassTemplateSpecializationDecl>(getDecl())) {
|
||||
std::string TemplateArgs
|
||||
= printTemplateArgumentList(Spec->getTemplateArgs(),
|
||||
Spec->getNumTemplateArgs());
|
||||
= ClassTemplateSpecializationType::PrintTemplateArgumentList(
|
||||
Spec->getTemplateArgs(),
|
||||
Spec->getNumTemplateArgs());
|
||||
InnerString = TemplateArgs + InnerString;
|
||||
}
|
||||
|
||||
|
|
|
@ -278,15 +278,19 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
|
|||
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];
|
||||
|
|
|
@ -245,7 +245,7 @@ public:
|
|||
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 @@ public:
|
|||
|
||||
/// \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 @@ public:
|
|||
/// 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 @@ public:
|
|||
/// 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 @@ public:
|
|||
Sema &SemaRef;
|
||||
bool Invalid;
|
||||
|
||||
bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
|
||||
SourceRange InstantiationRange);
|
||||
|
||||
InstantiatingTemplate(const InstantiatingTemplate&); // not implemented
|
||||
|
||||
InstantiatingTemplate&
|
||||
|
|
|
@ -825,10 +825,15 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
|
|||
|
||||
// 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 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
|
|||
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(),
|
||||
|
|
|
@ -30,19 +30,38 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
|
|||
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 = Entity;
|
||||
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 = 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 @@ Sema::InstantiatingTemplate::~InstantiatingTemplate() {
|
|||
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 @@ void Sema::PrintInstantiationStack() {
|
|||
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 @@ QualType Sema::InstantiateType(QualType T,
|
|||
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;
|
||||
|
|
|
@ -32,7 +32,8 @@ void test_Def2(Def2<int, int const*> *d2) {
|
|||
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'}}
|
||||
|
|
|
@ -15,4 +15,4 @@ Constant<float (*)(int, double), &f> *c5;
|
|||
|
||||
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}}
|
||||
|
|
Загрузка…
Ссылка в новой задаче