2008-12-06 02:15:24 +08:00
|
|
|
//===------- SemaTemplate.cpp - Semantic Analysis for C++ Templates -------===/
|
|
|
|
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//+//===----------------------------------------------------------------------===/
|
|
|
|
|
|
|
|
//
|
|
|
|
// This file implements semantic analysis for C++ templates.
|
|
|
|
//+//===----------------------------------------------------------------------===/
|
|
|
|
|
|
|
|
#include "Sema.h"
|
2008-12-06 07:32:09 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2008-12-06 02:15:24 +08:00
|
|
|
#include "clang/Parse/DeclSpec.h"
|
|
|
|
#include "clang/Basic/LangOptions.h"
|
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
2008-12-19 03:37:40 +08:00
|
|
|
/// isTemplateName - Determines whether the identifier II is a
|
|
|
|
/// template name in the current scope, and returns the template
|
|
|
|
/// declaration if II names a template. An optional CXXScope can be
|
|
|
|
/// passed to indicate the C++ scope in which the identifier will be
|
|
|
|
/// found.
|
|
|
|
Sema::DeclTy *Sema::isTemplateName(IdentifierInfo &II, Scope *S,
|
|
|
|
const CXXScopeSpec *SS) {
|
|
|
|
DeclContext *DC = 0;
|
2009-01-29 08:07:50 +08:00
|
|
|
|
2008-12-19 03:37:40 +08:00
|
|
|
if (SS) {
|
|
|
|
if (SS->isInvalid())
|
|
|
|
return 0;
|
|
|
|
DC = static_cast<DeclContext*>(SS->getScopeRep());
|
|
|
|
}
|
2009-02-05 01:27:36 +08:00
|
|
|
NamedDecl *IIDecl = LookupParsedName(S, SS, &II, LookupOrdinaryName);
|
2008-12-19 03:37:40 +08:00
|
|
|
|
|
|
|
if (IIDecl) {
|
|
|
|
// FIXME: We need to represent templates via some kind of
|
|
|
|
// TemplateDecl, because what follows is a hack that only works in
|
|
|
|
// one specific case.
|
|
|
|
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(IIDecl)) {
|
|
|
|
if (FD->getType()->isDependentType())
|
|
|
|
return FD;
|
|
|
|
} else if (OverloadedFunctionDecl *Ovl
|
|
|
|
= dyn_cast<OverloadedFunctionDecl>(IIDecl)) {
|
|
|
|
for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
|
|
|
|
FEnd = Ovl->function_end();
|
|
|
|
F != FEnd; ++F) {
|
|
|
|
if ((*F)->getType()->isDependentType())
|
|
|
|
return Ovl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-12-06 02:15:24 +08:00
|
|
|
/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
|
|
|
|
/// that the template parameter 'PrevDecl' is being shadowed by a new
|
|
|
|
/// declaration at location Loc. Returns true to indicate that this is
|
|
|
|
/// an error, and false otherwise.
|
|
|
|
bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) {
|
2008-12-09 02:40:42 +08:00
|
|
|
assert(PrevDecl->isTemplateParameter() && "Not a template parameter");
|
2008-12-06 02:15:24 +08:00
|
|
|
|
|
|
|
// Microsoft Visual C++ permits template parameters to be shadowed.
|
|
|
|
if (getLangOptions().Microsoft)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// C++ [temp.local]p4:
|
|
|
|
// A template-parameter shall not be redeclared within its
|
|
|
|
// scope (including nested scopes).
|
|
|
|
Diag(Loc, diag::err_template_param_shadow)
|
|
|
|
<< cast<NamedDecl>(PrevDecl)->getDeclName();
|
|
|
|
Diag(PrevDecl->getLocation(), diag::note_template_param_here);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ActOnTypeParameter - Called when a C++ template type parameter
|
|
|
|
/// (e.g., "typename T") has been parsed. Typename specifies whether
|
|
|
|
/// the keyword "typename" was used to declare the type parameter
|
|
|
|
/// (otherwise, "class" was used), and KeyLoc is the location of the
|
|
|
|
/// "class" or "typename" keyword. ParamName is the name of the
|
|
|
|
/// parameter (NULL indicates an unnamed template parameter) and
|
|
|
|
/// ParamName is the location of the parameter name (if any).
|
|
|
|
/// If the type parameter has a default argument, it will be added
|
|
|
|
/// later via ActOnTypeParameterDefault.
|
|
|
|
Sema::DeclTy *Sema::ActOnTypeParameter(Scope *S, bool Typename,
|
|
|
|
SourceLocation KeyLoc,
|
|
|
|
IdentifierInfo *ParamName,
|
2008-12-24 10:52:09 +08:00
|
|
|
SourceLocation ParamNameLoc,
|
|
|
|
unsigned Depth, unsigned Position) {
|
2008-12-06 02:15:24 +08:00
|
|
|
assert(S->isTemplateParamScope() &&
|
|
|
|
"Template type parameter not in template parameter scope!");
|
|
|
|
bool Invalid = false;
|
|
|
|
|
|
|
|
if (ParamName) {
|
2009-02-05 01:27:36 +08:00
|
|
|
NamedDecl *PrevDecl = LookupName(S, ParamName, LookupTagName);
|
2008-12-09 02:40:42 +08:00
|
|
|
if (PrevDecl && PrevDecl->isTemplateParameter())
|
2008-12-06 02:15:24 +08:00
|
|
|
Invalid = Invalid || DiagnoseTemplateParameterShadow(ParamNameLoc,
|
|
|
|
PrevDecl);
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *Param
|
|
|
|
= TemplateTypeParmDecl::Create(Context, CurContext,
|
|
|
|
ParamNameLoc, ParamName, Typename);
|
|
|
|
if (Invalid)
|
|
|
|
Param->setInvalidDecl();
|
|
|
|
|
|
|
|
if (ParamName) {
|
|
|
|
// Add the template parameter into the current scope.
|
|
|
|
S->AddDecl(Param);
|
|
|
|
IdResolver.AddDecl(Param);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Param;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ActOnNonTypeTemplateParameter - Called when a C++ non-type
|
|
|
|
/// template parameter (e.g., "int Size" in "template<int Size>
|
|
|
|
/// class Array") has been parsed. S is the current scope and D is
|
|
|
|
/// the parsed declarator.
|
2008-12-24 10:52:09 +08:00
|
|
|
Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
|
|
|
|
unsigned Depth,
|
|
|
|
unsigned Position) {
|
2008-12-06 02:15:24 +08:00
|
|
|
QualType T = GetTypeForDeclarator(D, S);
|
|
|
|
|
|
|
|
assert(S->isTemplateParamScope() &&
|
|
|
|
"Template type parameter not in template parameter scope!");
|
|
|
|
bool Invalid = false;
|
|
|
|
|
|
|
|
IdentifierInfo *ParamName = D.getIdentifier();
|
|
|
|
if (ParamName) {
|
2009-02-05 01:27:36 +08:00
|
|
|
NamedDecl *PrevDecl = LookupName(S, ParamName, LookupTagName);
|
2008-12-09 02:40:42 +08:00
|
|
|
if (PrevDecl && PrevDecl->isTemplateParameter())
|
2008-12-06 02:15:24 +08:00
|
|
|
Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
|
|
|
|
PrevDecl);
|
|
|
|
}
|
|
|
|
|
|
|
|
NonTypeTemplateParmDecl *Param
|
|
|
|
= NonTypeTemplateParmDecl::Create(Context, CurContext, D.getIdentifierLoc(),
|
|
|
|
ParamName, T);
|
|
|
|
if (Invalid)
|
|
|
|
Param->setInvalidDecl();
|
|
|
|
|
|
|
|
if (D.getIdentifier()) {
|
|
|
|
// Add the template parameter into the current scope.
|
|
|
|
S->AddDecl(Param);
|
|
|
|
IdResolver.AddDecl(Param);
|
|
|
|
}
|
|
|
|
return Param;
|
|
|
|
}
|
2008-12-24 10:52:09 +08:00
|
|
|
|
|
|
|
/// ActOnTemplateParameterList - Builds a TemplateParameterList that
|
|
|
|
/// contains the template parameters in Params/NumParams.
|
|
|
|
Sema::TemplateParamsTy *
|
|
|
|
Sema::ActOnTemplateParameterList(unsigned Depth,
|
|
|
|
SourceLocation ExportLoc,
|
|
|
|
SourceLocation TemplateLoc,
|
|
|
|
SourceLocation LAngleLoc,
|
|
|
|
DeclTy **Params, unsigned NumParams,
|
|
|
|
SourceLocation RAngleLoc) {
|
|
|
|
if (ExportLoc.isValid())
|
|
|
|
Diag(ExportLoc, diag::note_template_export_unsupported);
|
|
|
|
|
|
|
|
return TemplateParameterList::Create(Context, (Decl**)Params, NumParams);
|
|
|
|
}
|