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:
Sebastian Redl 2011-04-14 14:07:59 +00:00
parent 05d73a10a2
commit 9ab988fe00
8 changed files with 75 additions and 1 deletions

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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() { }

View File

@ -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