[cfe-commits] r73915 - in /cfe/trunk: lib/Parse/ParseDecl.cpp lib/Sema/Sema.cpp lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CodeGenCXX/implicit-instantiation-1.cpp test/SemaTemplate/example-dynarray.cpp
Douglas Gregor
dgregor at apple.com
Mon Jun 22 16:06:13 PDT 2009
Author: dgregor
Date: Mon Jun 22 18:06:13 2009
New Revision: 73915
URL: http://llvm.org/viewvc/llvm-project?rev=73915&view=rev
Log:
Implement implicit instantiation of the member functions of a class template
specialization. At present, all implicit instantiations occur at the
end of the translation unit.
Added:
cfe/trunk/test/CodeGenCXX/implicit-instantiation-1.cpp
Modified:
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaTemplate/example-dynarray.cpp
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=73915&r1=73914&r2=73915&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Jun 22 18:06:13 2009
@@ -273,7 +273,7 @@
/// [C++] template-declaration
/// [C++] namespace-definition
/// [C++] using-directive
-/// [C++] using-declaration [TODO]
+/// [C++] using-declaration
/// [C++0x] static_assert-declaration
/// others... [FIXME]
///
Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=73915&r1=73914&r2=73915&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Mon Jun 22 18:06:13 2009
@@ -235,6 +235,18 @@
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
void Sema::ActOnEndOfTranslationUnit() {
+ // C++: Perform implicit template instantiations.
+ //
+ // FIXME: When we perform these implicit instantiations, we do not carefully
+ // keep track of the point of instantiation (C++ [temp.point]). This means
+ // that name lookup that occurs within the template instantiation will
+ // always happen at the end of the translation unit, so it will find
+ // some names that should not be found. Although this is common behavior
+ // for C++ compilers, it is technically wrong. In the future, we either need
+ // to be able to filter the results of name lookup or we need to perform
+ // template instantiations earlier.
+ PerformPendingImplicitInstantiations();
+
if (!CompleteTranslationUnit)
return;
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=73915&r1=73914&r2=73915&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Jun 22 18:06:13 2009
@@ -31,6 +31,7 @@
#include "llvm/ADT/OwningPtr.h"
#include <list>
#include <string>
+#include <queue>
#include <vector>
namespace llvm {
@@ -2504,6 +2505,22 @@
/// variables.
LocalInstantiationScope *CurrentInstantiationScope;
+ /// \brief An entity for which implicit template instantiation is required.
+ ///
+ /// The source location associated with the declaration is the first place in
+ /// the source code where the declaration was "used". It is not necessarily
+ /// the point of instantiation (which will be either before or after the
+ /// namespace-scope declaration that triggered this implicit instantiation),
+ /// However, it is the location that diagnostics should generally refer to,
+ /// because users will need to know what code triggered the instantiation.
+ typedef std::pair<ValueDecl *, SourceLocation> PendingImplicitInstantiation;
+
+ /// \brief The queue of implicit template instantiations that are required
+ /// but have not yet been performed.
+ std::queue<PendingImplicitInstantiation> PendingImplicitInstantiations;
+
+ void PerformPendingImplicitInstantiations();
+
QualType InstantiateType(QualType T, const TemplateArgumentList &TemplateArgs,
SourceLocation Loc, DeclarationName Entity);
@@ -2559,7 +2576,7 @@
void InstantiateVariableDefinition(VarDecl *Var);
NamedDecl *InstantiateCurrentDeclRef(NamedDecl *D);
-
+
// Simple function for cloning expressions.
template<typename T>
OwningExprResult Clone(T *E) {
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=73915&r1=73914&r2=73915&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Jun 22 18:06:13 2009
@@ -1921,6 +1921,7 @@
Expr **Exprs, unsigned NumExprs) {
Expr *Temp = CXXConstructExpr::Create(Context, DeclInitType, Constructor,
false, Exprs, NumExprs);
+ MarkDeclarationReferenced(VD->getLocation(), Constructor);
VD->setInit(Context, Temp);
}
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=73915&r1=73914&r2=73915&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Jun 22 18:06:13 2009
@@ -2134,25 +2134,32 @@
MemberType = MemberType.getQualifiedType(combinedQualifiers);
}
+ MarkDeclarationReferenced(MemberLoc, FD);
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, FD,
MemberLoc, MemberType));
}
- if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl))
+ if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
+ MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow,
Var, MemberLoc,
Var->getType().getNonReferenceType()));
- if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl))
+ }
+ if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) {
+ MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow,
MemberFn, MemberLoc,
MemberFn->getType()));
+ }
if (OverloadedFunctionDecl *Ovl
= dyn_cast<OverloadedFunctionDecl>(MemberDecl))
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, Ovl,
MemberLoc, Context.OverloadTy));
- if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl))
+ if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
+ MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow,
Enum, MemberLoc, Enum->getType()));
+ }
if (isa<TypeDecl>(MemberDecl))
return ExprError(Diag(MemberLoc,diag::err_typecheck_member_reference_type)
<< DeclarationName(&Member) << int(OpKind == tok::arrow));
@@ -5475,6 +5482,9 @@
void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
assert(D && "No declaration?");
+ if (D->isUsed())
+ return;
+
// Mark a parameter declaration "used", regardless of whether we're in a
// template or not.
if (isa<ParmVarDecl>(D))
@@ -5512,16 +5522,22 @@
// FIXME: more checking for other implicits go here.
else
Constructor->setUsed(true);
- return;
}
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
- // FIXME: implicit template instantiation
+ // Implicit instantiation of function templates
+ if (!Function->getBody(Context)) {
+ if (Function->getInstantiatedFromMemberFunction())
+ PendingImplicitInstantiations.push(std::make_pair(Function, Loc));
+
+ // FIXME: check for function template specializations.
+ }
+
+
// FIXME: keep track of references to static functions
- (void)Function;
Function->setUsed(true);
return;
- }
+ }
if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
(void)Var;
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=73915&r1=73914&r2=73915&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Jun 22 18:06:13 2009
@@ -597,6 +597,8 @@
if (Function->isInvalidDecl())
return;
+ assert(!Function->getBody(Context) && "Already instantiated!");
+
// Find the function body that we'll be substituting.
const FunctionDecl *PatternDecl
= Function->getInstantiatedFromMemberFunction();
@@ -776,3 +778,18 @@
return D;
}
+
+/// \brief Performs template instantiation for all implicit template
+/// instantiations we have seen until this point.
+void Sema::PerformPendingImplicitInstantiations() {
+ while (!PendingImplicitInstantiations.empty()) {
+ PendingImplicitInstantiation Inst = PendingImplicitInstantiations.front();
+ PendingImplicitInstantiations.pop();
+
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first))
+ if (!Function->getBody(Context))
+ InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function);
+
+ // FIXME: instantiation static member variables
+ }
+}
Added: cfe/trunk/test/CodeGenCXX/implicit-instantiation-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/implicit-instantiation-1.cpp?rev=73915&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/implicit-instantiation-1.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/implicit-instantiation-1.cpp Mon Jun 22 18:06:13 2009
@@ -0,0 +1,29 @@
+// RUN: clang-cc -emit-llvm %s -o %t &&
+
+template<typename T>
+struct X {
+ void f(T) { }
+ void f(char) { }
+
+ void g(T) { }
+
+ void h(T) { }
+};
+
+void foo(X<int> &xi, X<float> *xfp, int i, float f) {
+ // RUN: grep "linkonce_odr.*_ZN1XIiE1fEi" %t | count 1 &&
+ xi.f(i);
+
+ // RUN: grep "linkonce_odr.*_ZN1XIiE1gEi" %t | count 1 &&
+ xi.g(f);
+
+ // RUN: grep "linkonce_odr.*_ZN1XIfE1fEf" %t | count 1 &&
+ xfp->f(f);
+
+ // RUN: grep "linkonce_odr.*_ZN1XIfE1hEf" %t | count 0 &&
+
+ // RUN: true
+}
+
+
+
Modified: cfe/trunk/test/SemaTemplate/example-dynarray.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/example-dynarray.cpp?rev=73915&r1=73914&r2=73915&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/example-dynarray.cpp (original)
+++ cfe/trunk/test/SemaTemplate/example-dynarray.cpp Mon Jun 22 18:06:13 2009
@@ -89,6 +89,21 @@
iterator end() { return Last; }
const_iterator end() const { return Last; }
+ bool operator==(const dynarray &other) const {
+ if (size() != other.size())
+ return false;
+
+ for (unsigned I = 0, N = size(); I != N; ++I)
+ if ((*this)[I] != other[I])
+ return false;
+
+ return true;
+ }
+
+ bool operator!=(const dynarray &other) const {
+ return !(*this == other);
+ }
+
public:
T* Start, *Last, *End;
};
@@ -100,11 +115,6 @@
float x, y, z;
};
-// FIXME: remove these when we have implicit instantiation for member
-// functions of class templates.
-template class dynarray<int>;
-template class dynarray<Point>;
-
int main() {
dynarray<int> di;
di.push_back(0);
@@ -146,5 +156,13 @@
I != IEnd; ++I)
assert(*I == I - di4.begin());
+ assert(di4 == di);
+ di4[3] = 17;
+ assert(di4 != di);
+
+ dynarray<Point> dp;
+ dp.push_back(Point());
+ assert(dp.size() == 1);
+
return 0;
}
More information about the cfe-commits
mailing list