forked from OSchip/llvm-project
Chained PCH: Remember when additional specializations are added to a function template from a previous PCH. Fixes the only crasher when using massive chains on Clang's Sema component. We still have some incomplete codegen there.
llvm-svn: 129516
This commit is contained in:
parent
05d73a10a2
commit
9ab988fe00
|
@ -20,6 +20,8 @@ namespace clang {
|
|||
class CXXRecordDecl;
|
||||
class ClassTemplateDecl;
|
||||
class ClassTemplateSpecializationDecl;
|
||||
class FunctionDecl;
|
||||
class FunctionTemplateDecl;
|
||||
|
||||
/// \brief An abstract interface that should be implemented by listeners
|
||||
/// that want to be notified when an AST entity gets modified after its
|
||||
|
@ -41,6 +43,11 @@ public:
|
|||
/// template declaration.
|
||||
virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
|
||||
const ClassTemplateSpecializationDecl *D) {}
|
||||
|
||||
/// \brief A template specialization (or partial one) was added to the
|
||||
/// template declaration.
|
||||
virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
|
||||
const FunctionDecl *D) {}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
@ -804,6 +804,13 @@ protected:
|
|||
llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
|
||||
return getCommonPtr()->Specializations;
|
||||
}
|
||||
|
||||
/// \brief Add a specialization of this function template.
|
||||
///
|
||||
/// \param InsertPos Insert position in the FoldingSet, must have been
|
||||
/// retrieved by an earlier call to findSpecialization().
|
||||
void addSpecialization(FunctionTemplateSpecializationInfo* Info,
|
||||
void *InsertPos);
|
||||
|
||||
public:
|
||||
/// Get the underlying function declaration of the template.
|
||||
|
|
|
@ -586,6 +586,8 @@ public:
|
|||
virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D);
|
||||
virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
|
||||
const ClassTemplateSpecializationDecl *D);
|
||||
virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
|
||||
const FunctionDecl *D);
|
||||
};
|
||||
|
||||
/// \brief AST and semantic-analysis consumer that generates a
|
||||
|
|
|
@ -1893,7 +1893,7 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
|
|||
// Insert this function template specialization into the set of known
|
||||
// function template specializations.
|
||||
if (InsertPos)
|
||||
Template->getSpecializations().InsertNode(Info, InsertPos);
|
||||
Template->addSpecialization(Info, InsertPos);
|
||||
else {
|
||||
// Try to insert the new node. If there is an existing node, leave it, the
|
||||
// set will contain the canonical decls while
|
||||
|
|
|
@ -242,6 +242,13 @@ FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
|
|||
return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos);
|
||||
}
|
||||
|
||||
void FunctionTemplateDecl::addSpecialization(
|
||||
FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
|
||||
getSpecializations().InsertNode(Info, InsertPos);
|
||||
if (ASTMutationListener *L = getASTMutationListener())
|
||||
L->AddedCXXTemplateSpecialization(this, Info->Function);
|
||||
}
|
||||
|
||||
std::pair<const TemplateArgument *, unsigned>
|
||||
FunctionTemplateDecl::getInjectedTemplateArgs() {
|
||||
TemplateParameterList *Params = getTemplateParameters();
|
||||
|
|
|
@ -95,6 +95,8 @@ public:
|
|||
virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D);
|
||||
virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
|
||||
const ClassTemplateSpecializationDecl *D);
|
||||
virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
|
||||
const FunctionDecl *D);
|
||||
private:
|
||||
std::vector<ASTMutationListener*> Listeners;
|
||||
};
|
||||
|
@ -125,6 +127,11 @@ void MultiplexASTMutationListener::AddedCXXTemplateSpecialization(
|
|||
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
|
||||
Listeners[i]->AddedCXXTemplateSpecialization(TD, D);
|
||||
}
|
||||
void MultiplexASTMutationListener::AddedCXXTemplateSpecialization(
|
||||
const FunctionTemplateDecl *TD, const FunctionDecl *D) {
|
||||
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
|
||||
Listeners[i]->AddedCXXTemplateSpecialization(TD, D);
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
|
|
|
@ -3936,4 +3936,16 @@ void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
|
|||
AddDeclRef(D, Record);
|
||||
}
|
||||
|
||||
void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
|
||||
const FunctionDecl *D) {
|
||||
// The specializations set is kept in the canonical template.
|
||||
TD = TD->getCanonicalDecl();
|
||||
if (!(D->getPCHLevel() == 0 && TD->getPCHLevel() > 0))
|
||||
return; // Not a source specialization added to a template from PCH.
|
||||
|
||||
UpdateRecord &Record = DeclUpdates[TD];
|
||||
Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
|
||||
AddDeclRef(D, Record);
|
||||
}
|
||||
|
||||
ASTSerializationListener::~ASTSerializationListener() { }
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// RUN: %clang_cc1 -chain-include %s -chain-include %s -fsyntax-only %s
|
||||
// Just don't crash.
|
||||
#if !defined(RUN1)
|
||||
#define RUN1
|
||||
|
||||
struct CXXRecordDecl { CXXRecordDecl(int); };
|
||||
|
||||
template <typename T, typename U>
|
||||
T cast(U u) {
|
||||
return reinterpret_cast<T&>(u);
|
||||
}
|
||||
|
||||
void test1() {
|
||||
cast<float>(1);
|
||||
}
|
||||
|
||||
#elif !defined(RUN2)
|
||||
#define RUN2
|
||||
|
||||
template <typename T>
|
||||
void test2(T) {
|
||||
cast<CXXRecordDecl>(1.0f);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void test3() {
|
||||
cast<CXXRecordDecl>(1.0f);
|
||||
test2(1);
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue