diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-12-05 18:15:24 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-12-05 18:15:24 +0000 |
commit | 72c3f314d92d65c050ee1c07b7753623c044d6c7 (patch) | |
tree | d714ab61b37fb6732d556e9f324181a41312cffa /lib/Sema/SemaTemplate.cpp | |
parent | 8c56515a0c61b73fc2f02cc96dc3e37650d89d45 (diff) |
Representation of template type parameters and non-type template
parameters, with some semantic analysis:
- Template parameters are introduced into template parameter scope
- Complain about template parameter shadowing (except in Microsoft mode)
Note that we leak template parameter declarations like crazy, a
problem we'll remedy once we actually create proper declarations for
templates.
Next up: dependent types and value-dependent/type-dependent
expressions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60597 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp new file mode 100644 index 0000000000..749d181baf --- /dev/null +++ b/lib/Sema/SemaTemplate.cpp @@ -0,0 +1,116 @@ +//===------- 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" +#include "clang/Parse/DeclSpec.h" +#include "clang/Basic/LangOptions.h" + +using namespace clang; + +/// isTemplateParameterDecl - Determines whether the given declaration +/// 'D' names a template parameter. +bool Sema::isTemplateParameterDecl(Decl *D) { + return isa<TemplateTypeParmDecl>(D) || isa<NonTypeTemplateParmDecl>(D); +} + +/// 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) { + assert(isTemplateParameterDecl(PrevDecl) && "Not a template parameter"); + + // 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, + SourceLocation ParamNameLoc) { + assert(S->isTemplateParamScope() && + "Template type parameter not in template parameter scope!"); + bool Invalid = false; + + if (ParamName) { + Decl *PrevDecl = LookupDecl(ParamName, Decl::IDNS_Tag, S); + if (PrevDecl && isTemplateParameterDecl(PrevDecl)) + 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. +Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D) { + 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) { + Decl *PrevDecl = LookupDecl(ParamName, Decl::IDNS_Tag, S); + if (PrevDecl && isTemplateParameterDecl(PrevDecl)) + 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; +} |