mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 15:41:46 +00:00
When instantiating the definition of a member function of a class
template, introduce that member function into the template instantiation stack. Also, add diagnostics showing the member function within the instantiation stack and clean up the qualified-name printing so that we get something like: note: in instantiation of member function 'Switch1<int, 2, 2>::f' requested here in the template instantiation backtrace. llvm-svn: 72015
This commit is contained in:
parent
f811647c27
commit
8567358cc9
@ -745,6 +745,8 @@ def note_template_class_instantiation_here : Note<
|
||||
"in instantiation of template class %0 requested here">;
|
||||
def note_template_member_class_here : Note<
|
||||
"in instantiation of member class %0 requested here">;
|
||||
def note_template_member_function_here : Note<
|
||||
"in instantiation of member function %q0 requested here">;
|
||||
def note_default_arg_instantiation_here : Note<
|
||||
"in instantiation of default argument for '%0' required here">;
|
||||
def err_field_instantiates_to_function : Error<
|
||||
|
@ -212,7 +212,15 @@ std::string NamedDecl::getQualifiedNameAsString() const {
|
||||
// scope class/struct/union. How do we handle this case?
|
||||
break;
|
||||
|
||||
if (const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx))
|
||||
if (const ClassTemplateSpecializationDecl *Spec
|
||||
= dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
|
||||
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
|
||||
std::string TemplateArgsStr
|
||||
= TemplateSpecializationType::PrintTemplateArgumentList(
|
||||
TemplateArgs.getFlatArgumentList(),
|
||||
TemplateArgs.flat_size());
|
||||
Names.push_back(Spec->getIdentifier()->getName() + TemplateArgsStr);
|
||||
} else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx))
|
||||
Names.push_back(ND->getNameAsString());
|
||||
else
|
||||
break;
|
||||
|
@ -2070,9 +2070,10 @@ public:
|
||||
/// Destruction of this object will pop the named instantiation off
|
||||
/// the stack.
|
||||
struct InstantiatingTemplate {
|
||||
/// \brief Note that we are instantiating a class template.
|
||||
/// \brief Note that we are instantiating a class template,
|
||||
/// function template, or a member thereof.
|
||||
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
|
||||
CXXRecordDecl *Entity,
|
||||
Decl *Entity,
|
||||
SourceRange InstantiationRange = SourceRange());
|
||||
|
||||
/// \brief Note that we are instantiating a default argument in a
|
||||
@ -2083,7 +2084,10 @@ public:
|
||||
unsigned NumTemplateArgs,
|
||||
SourceRange InstantiationRange = SourceRange());
|
||||
|
||||
~InstantiatingTemplate();
|
||||
/// \brief Note that we have finished instantiating this template.
|
||||
void Clear();
|
||||
|
||||
~InstantiatingTemplate() { Clear(); }
|
||||
|
||||
/// \brief Determines whether we have exceeded the maximum
|
||||
/// recursive template instantiations.
|
||||
@ -2216,7 +2220,8 @@ public:
|
||||
InstantiateTemplateName(TemplateName Name, SourceLocation Loc,
|
||||
const TemplateArgumentList &TemplateArgs);
|
||||
|
||||
void InstantiateFunctionDefinition(FunctionDecl *Function);
|
||||
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||
FunctionDecl *Function);
|
||||
void InstantiateVariableDefinition(VarDecl *Var);
|
||||
|
||||
// Simple function for cloning expressions.
|
||||
|
@ -2340,11 +2340,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
|
||||
// instantiation.
|
||||
if (SpecializationRequiresInstantiation)
|
||||
InstantiateClassTemplateSpecialization(Specialization, true);
|
||||
else {
|
||||
// Instantiate the members of this class template specialization.
|
||||
InstantiatingTemplate Inst(*this, TemplateLoc, Specialization);
|
||||
else // Instantiate the members of this class template specialization.
|
||||
InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization);
|
||||
}
|
||||
|
||||
return DeclPtrTy::make(Specialization);
|
||||
}
|
||||
@ -2405,12 +2402,9 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
|
||||
getTemplateInstantiationArgs(Record),
|
||||
/*ExplicitInstantiation=*/true))
|
||||
return true;
|
||||
} else {
|
||||
// Instantiate all of the members of class.
|
||||
InstantiatingTemplate Inst(*this, TemplateLoc, Record);
|
||||
} else // Instantiate all of the members of class.
|
||||
InstantiateClassMembers(TemplateLoc, Record,
|
||||
getTemplateInstantiationArgs(Record));
|
||||
}
|
||||
|
||||
// FIXME: We don't have any representation for explicit instantiations of
|
||||
// member classes. Such a representation is not needed for compilation, but it
|
||||
|
@ -46,7 +46,7 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D) {
|
||||
|
||||
Sema::InstantiatingTemplate::
|
||||
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
|
||||
CXXRecordDecl *Entity,
|
||||
Decl *Entity,
|
||||
SourceRange InstantiationRange)
|
||||
: SemaRef(SemaRef) {
|
||||
|
||||
@ -89,9 +89,11 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
|
||||
}
|
||||
}
|
||||
|
||||
Sema::InstantiatingTemplate::~InstantiatingTemplate() {
|
||||
if (!Invalid)
|
||||
void Sema::InstantiatingTemplate::Clear() {
|
||||
if (!Invalid) {
|
||||
SemaRef.ActiveTemplateInstantiations.pop_back();
|
||||
Invalid = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
|
||||
@ -120,14 +122,24 @@ void Sema::PrintInstantiationStack() {
|
||||
++Active) {
|
||||
switch (Active->Kind) {
|
||||
case ActiveTemplateInstantiation::TemplateInstantiation: {
|
||||
unsigned DiagID = diag::note_template_member_class_here;
|
||||
CXXRecordDecl *Record = (CXXRecordDecl *)Active->Entity;
|
||||
if (isa<ClassTemplateSpecializationDecl>(Record))
|
||||
DiagID = diag::note_template_class_instantiation_here;
|
||||
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
||||
DiagID)
|
||||
<< Context.getTypeDeclType(Record)
|
||||
<< Active->InstantiationRange;
|
||||
Decl *D = reinterpret_cast<Decl *>(Active->Entity);
|
||||
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
|
||||
unsigned DiagID = diag::note_template_member_class_here;
|
||||
if (isa<ClassTemplateSpecializationDecl>(Record))
|
||||
DiagID = diag::note_template_class_instantiation_here;
|
||||
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
||||
DiagID)
|
||||
<< Context.getTypeDeclType(Record)
|
||||
<< Active->InstantiationRange;
|
||||
} else {
|
||||
FunctionDecl *Function = cast<FunctionDecl>(D);
|
||||
unsigned DiagID = diag::note_template_member_function_here;
|
||||
// FIXME: check for a function template
|
||||
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
|
||||
DiagID)
|
||||
<< Function
|
||||
<< Active->InstantiationRange;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -768,8 +780,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
|
||||
CurContext = PreviousContext;
|
||||
|
||||
// If this is an explicit instantiation, instantiate our members, too.
|
||||
if (!Invalid && ExplicitInstantiation)
|
||||
if (!Invalid && ExplicitInstantiation) {
|
||||
Inst.Clear();
|
||||
InstantiateClassMembers(PointOfInstantiation, Instantiation, TemplateArgs);
|
||||
}
|
||||
|
||||
return Invalid;
|
||||
}
|
||||
@ -820,7 +834,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
||||
D != DEnd; ++D) {
|
||||
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
|
||||
if (!Function->getBody(Context))
|
||||
InstantiateFunctionDefinition(Function);
|
||||
InstantiateFunctionDefinition(PointOfInstantiation, Function);
|
||||
} else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
|
||||
const VarDecl *Def = 0;
|
||||
if (!Var->getDefinition(Def))
|
||||
@ -829,7 +843,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
||||
if (!Record->isInjectedClassName() && !Record->getDefinition(Context)) {
|
||||
assert(Record->getInstantiatedFromMemberClass() &&
|
||||
"Missing instantiated-from-template information");
|
||||
InstantiateClass(Record->getLocation(), Record,
|
||||
InstantiateClass(PointOfInstantiation, Record,
|
||||
Record->getInstantiatedFromMemberClass(),
|
||||
TemplateArgs, true);
|
||||
}
|
||||
|
@ -574,7 +574,8 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
|
||||
///
|
||||
/// \param Function the already-instantiated declaration of a
|
||||
/// function.
|
||||
void Sema::InstantiateFunctionDefinition(FunctionDecl *Function) {
|
||||
void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||
FunctionDecl *Function) {
|
||||
// FIXME: make this work for function template specializations, too.
|
||||
|
||||
if (Function->isInvalidDecl())
|
||||
@ -590,7 +591,9 @@ void Sema::InstantiateFunctionDefinition(FunctionDecl *Function) {
|
||||
if (!Pattern)
|
||||
return;
|
||||
|
||||
// FIXME: add to the instantiation stack.
|
||||
InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
|
||||
if (Inst)
|
||||
return;
|
||||
|
||||
ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function));
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
// RUN: clang-cc -fsyntax-only %s
|
||||
template<typename T, typename U>
|
||||
struct X0 {
|
||||
void f(T x, U y) {
|
||||
@ -47,8 +47,8 @@ template <typename T> struct X4 {
|
||||
}
|
||||
};
|
||||
|
||||
template struct X4<void>; // expected-note{{in instantiation of template class 'X4<void>' requested here}}
|
||||
template struct X4<int>; // expected-note{{in instantiation of template class 'X4<int>' requested here}}
|
||||
template struct X4<void>; // expected-note{{in instantiation of}}
|
||||
template struct X4<int>; // expected-note{{in instantiation of}}
|
||||
|
||||
struct Incomplete; // expected-note{{forward declaration}}
|
||||
|
||||
|
@ -49,7 +49,7 @@ template struct X2<int&>; // expected-note{{in instantiation of}}
|
||||
|
||||
// Check that explicit instantiations instantiate member classes.
|
||||
template<typename T> struct X3 {
|
||||
struct Inner { // expected-note{{here}}
|
||||
struct Inner {
|
||||
void f(T*); // expected-error{{pointer to a reference}}
|
||||
};
|
||||
};
|
||||
@ -59,8 +59,8 @@ void f1(X3<int&>); // okay, Inner, not instantiated
|
||||
template struct X3<int&>; // expected-note{{instantiation}}
|
||||
|
||||
template<typename T> struct X4 {
|
||||
struct Inner { // expected-note 2{{here}}
|
||||
struct VeryInner { // expected-note 2{{here}}
|
||||
struct Inner {
|
||||
struct VeryInner {
|
||||
void f(T*); // expected-error 2{{pointer to a reference}}
|
||||
};
|
||||
};
|
||||
@ -82,7 +82,7 @@ struct X5 {
|
||||
};
|
||||
|
||||
struct Inner2 {
|
||||
struct VeryInner { // expected-note 2{{instantiation}}
|
||||
struct VeryInner {
|
||||
void g(T*); // expected-error 2{{pointer to a reference}}
|
||||
};
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user