Tweak the semantics of FunctionDecl::isOutOfLine to consider an

instantiation of a member function template or member function of a
class template to be out-of-line if the definition of that function
template or member function was defined out-of-line. This ensures that
we get the correct linkage for explicit instantiations of out-of-line
definitions. 



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81562 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2009-09-11 20:15:17 +00:00
Родитель d5d6778fb9
Коммит 9f185076dc
5 изменённых файлов: 31 добавлений и 7 удалений

Просмотреть файл

@ -1137,6 +1137,10 @@ public:
/// represents.
void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
/// \brief Determine whether this is or was instantiated from an out-of-line
/// definition of a member function.
bool isOutOfLine() const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast;

Просмотреть файл

@ -757,7 +757,7 @@ public:
return isVirtualAsWritten() ||
(begin_overridden_methods() != end_overridden_methods());
}
///
void addOverriddenMethod(const CXXMethodDecl *MD);

Просмотреть файл

@ -704,6 +704,30 @@ FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
Info->setTemplateSpecializationKind(TSK);
}
bool FunctionDecl::isOutOfLine() const {
// FIXME: Should we restrict this to member functions?
if (Decl::isOutOfLine())
return true;
// If this function was instantiated from a member function of a
// class template, check whether that member function was defined out-of-line.
if (FunctionDecl *FD = getInstantiatedFromMemberFunction()) {
const FunctionDecl *Definition;
if (FD->getBody(Definition))
return Definition->isOutOfLine();
}
// If this function was instantiated from a function template,
// check whether that function template was defined out-of-line.
if (FunctionTemplateDecl *FunTmpl = getPrimaryTemplate()) {
const FunctionDecl *Definition;
if (FunTmpl->getTemplatedDecl()->getBody(Definition))
return Definition->isOutOfLine();
}
return false;
}
//===----------------------------------------------------------------------===//
// TagDecl Implementation
//===----------------------------------------------------------------------===//

Просмотреть файл

@ -344,7 +344,6 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
isStatic, isInline);
}
typedef llvm::DenseMap<const CXXMethodDecl*,
std::vector<const CXXMethodDecl *> *>
OverriddenMethodsMapTy;

Просмотреть файл

@ -1,9 +1,6 @@
// RUN: clang-cc -emit-llvm -femit-all-decls -o %t %s &&
// RUN: grep "_ZNK4plusIillEclERKiRKl" %t | count 1
// RUN: clang-cc -emit-llvm -triple i686-pc-linue-gnu -o %t %s &&
// RUN: grep "define i32 @_ZNK4plusIillEclERKiRKl" %t | count 1
// FIXME: We should not need the -femit-all-decls, because operator() should
// be emitted as an external symbol rather than with linkonce_odr linkage.
// This is a Sema problem.
template<typename T, typename U, typename Result>
struct plus {
Result operator()(const T& t, const U& u) const;