[cfe-commits] r82806 - in /cfe/trunk: include/clang/Parse/DeclSpec.h lib/Parse/ParseDecl.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaType.cpp test/SemaTemplate/explicit-instantiation.cpp
Douglas Gregor
dgregor at apple.com
Fri Sep 25 14:45:24 PDT 2009
Author: dgregor
Date: Fri Sep 25 16:45:23 2009
New Revision: 82806
URL: http://llvm.org/viewvc/llvm-project?rev=82806&view=rev
Log:
Declarators can now properly represent template-ids, e.g., for
template void f<int>(int);
~~~~~~
Previously, we silently dropped the template arguments. With this
change, we now use the template arguments (when available) as the
explicitly-specified template arguments used to aid template argument
deduction for explicit template instantiations.
Modified:
cfe/trunk/include/clang/Parse/DeclSpec.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp
Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=82806&r1=82805&r2=82806&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Fri Sep 25 16:45:23 2009
@@ -794,8 +794,10 @@
DK_Constructor, // A C++ constructor (identifier is the class name)
DK_Destructor, // A C++ destructor (identifier is ~class name)
DK_Operator, // A C++ overloaded operator name
- DK_Conversion // A C++ conversion function (identifier is
+ DK_Conversion, // A C++ conversion function (identifier is
// "operator " then the type name)
+ DK_TemplateId // A C++ template-id naming a function template
+ // specialization.
};
private:
@@ -839,6 +841,10 @@
/// When Kind is DK_Operator, this is the actual overloaded
/// operator that this declarator names.
OverloadedOperatorKind OperatorKind;
+
+ /// When Kind is DK_TemplateId, this is the template-id annotation that
+ /// contains the template and its template arguments.
+ TemplateIdAnnotation *TemplateId;
};
/// InlineParams - This is a local array used for the first function decl
@@ -916,6 +922,10 @@
Identifier = 0;
IdentifierLoc = SourceLocation();
Range = DS.getSourceRange();
+
+ if (Kind == DK_TemplateId)
+ TemplateId->Destroy();
+
Kind = DK_Abstract;
for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i)
@@ -1023,6 +1033,16 @@
SetRangeEnd(EndLoc);
}
+ /// \brief Set this declaration to be a C++ template-id, which includes the
+ /// template (or set of function templates) along with template arguments.
+ void setTemplateId(TemplateIdAnnotation *TemplateId) {
+ assert(TemplateId && "NULL template-id provided to declarator?");
+ IdentifierLoc = TemplateId->TemplateNameLoc;
+ Kind = DK_TemplateId;
+ SetRangeEnd(TemplateId->RAngleLoc);
+ this->TemplateId = TemplateId;
+ }
+
/// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
/// EndLoc, which should be the last token of the chunk.
void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) {
@@ -1085,10 +1105,22 @@
void setExtension(bool Val = true) { Extension = Val; }
bool getExtension() const { return Extension; }
- ActionBase::TypeTy *getDeclaratorIdType() const { return Type; }
+ ActionBase::TypeTy *getDeclaratorIdType() const {
+ assert((Kind == DK_Constructor || Kind == DK_Destructor ||
+ Kind == DK_Conversion) && "Declarator kind does not have a type");
+ return Type;
+ }
- OverloadedOperatorKind getOverloadedOperator() const { return OperatorKind; }
+ OverloadedOperatorKind getOverloadedOperator() const {
+ assert(Kind == DK_Operator && "Declarator is not an overloaded operator");
+ return OperatorKind;
+ }
+ TemplateIdAnnotation *getTemplateId() {
+ assert(Kind == DK_TemplateId && "Declarator is not a template-id");
+ return TemplateId;
+ }
+
void setInvalidType(bool Val = true) { InvalidType = Val; }
bool isInvalidType() const {
return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error;
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=82806&r1=82805&r2=82806&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Sep 25 16:45:23 2009
@@ -2210,12 +2210,12 @@
///
/// id-expression: [C++ 5.1]
/// unqualified-id
-/// qualified-id [TODO]
+/// qualified-id
///
/// unqualified-id: [C++ 5.1]
/// identifier
/// operator-function-id
-/// conversion-function-id [TODO]
+/// conversion-function-id
/// '~' class-name
/// template-id
///
@@ -2254,15 +2254,7 @@
TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
- // FIXME: Could this template-id name a constructor?
-
- // FIXME: This is an egregious hack, where we silently ignore
- // the specialization (which should be a function template
- // specialization name) and use the name instead. This hack
- // will go away when we have support for function
- // specializations.
- D.SetIdentifier(TemplateId->Name, Tok.getLocation());
- TemplateId->Destroy();
+ D.setTemplateId(TemplateId);
ConsumeToken();
goto PastIdentifier;
} else if (Tok.is(tok::kw_operator)) {
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=82806&r1=82805&r2=82806&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Sep 25 16:45:23 2009
@@ -1587,6 +1587,17 @@
assert(D.getIdentifier() == 0 && "operator names have no identifier");
return Context.DeclarationNames.getCXXOperatorName(
D.getOverloadedOperator());
+
+ case Declarator::DK_TemplateId: {
+ TemplateName Name
+ = TemplateName::getFromVoidPointer(D.getTemplateId()->Template);
+ if (TemplateDecl *Template = Name.getAsTemplateDecl())
+ return Template->getDeclName();
+ if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl())
+ return Ovl->getDeclName();
+
+ return DeclarationName();
+ }
}
assert(false && "Unknown name kind");
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=82806&r1=82805&r2=82806&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Sep 25 16:45:23 2009
@@ -3409,23 +3409,38 @@
return DeclPtrTy();
}
+ // Translate the parser's template argument list in our AST format.
+ bool HasExplicitTemplateArgs = false;
+ llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+ if (D.getKind() == Declarator::DK_TemplateId) {
+ TemplateIdAnnotation *TemplateId = D.getTemplateId();
+ ASTTemplateArgsPtr TemplateArgsPtr(*this,
+ TemplateId->getTemplateArgs(),
+ TemplateId->getTemplateArgIsType(),
+ TemplateId->NumArgs);
+ translateTemplateArguments(TemplateArgsPtr,
+ TemplateId->getTemplateArgLocations(),
+ TemplateArgs);
+ HasExplicitTemplateArgs = true;
+ }
+
+
// C++ [temp.explicit]p1:
// A [...] function [...] can be explicitly instantiated from its template.
// A member function [...] of a class template can be explicitly
// instantiated from the member definition associated with its class
// template.
- // FIXME: Implement this!
llvm::SmallVector<FunctionDecl *, 8> Matches;
for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
P != PEnd; ++P) {
NamedDecl *Prev = *P;
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
- // FIXME: If there were any explicitly-specified template arguments,
- // don't look for Method declarations.
- if (Context.hasSameUnqualifiedType(Method->getType(), R)) {
- Matches.clear();
- Matches.push_back(Method);
- break;
+ if (!HasExplicitTemplateArgs) {
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
+ if (Context.hasSameUnqualifiedType(Method->getType(), R)) {
+ Matches.clear();
+ Matches.push_back(Method);
+ break;
+ }
}
}
@@ -3436,7 +3451,8 @@
TemplateDeductionInfo Info(Context);
FunctionDecl *Specialization = 0;
if (TemplateDeductionResult TDK
- = DeduceTemplateArguments(FunTmpl, /*FIXME:*/false, 0, 0,
+ = DeduceTemplateArguments(FunTmpl, HasExplicitTemplateArgs,
+ TemplateArgs.data(), TemplateArgs.size(),
R, Specialization, Info)) {
// FIXME: Keep track of almost-matches?
(void)TDK;
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=82806&r1=82805&r2=82806&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Fri Sep 25 16:45:23 2009
@@ -842,7 +842,8 @@
switch (D.getKind()) {
case Declarator::DK_Abstract:
case Declarator::DK_Normal:
- case Declarator::DK_Operator: {
+ case Declarator::DK_Operator:
+ case Declarator::DK_TemplateId: {
const DeclSpec &DS = D.getDeclSpec();
if (OmittedReturnType) {
// We default to a dependent type initially. Can be modified by
Modified: cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp?rev=82806&r1=82805&r2=82806&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp (original)
+++ cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp Fri Sep 25 16:45:23 2009
@@ -55,3 +55,17 @@
template int *X2::f1(int *); // okay
template void X2::f2(int *, int *); // expected-error{{ambiguous}}
+
+
+template<typename T> void print_type();
+
+template void print_type<int>();
+template void print_type<float>();
+
+template<typename T> void print_type(T*);
+
+template void print_type(int*);
+template void print_type<int>(float*); // expected-error{{does not refer}}
+
+void print_type(double*);
+template void print_type<double>(double*);
More information about the cfe-commits
mailing list