blob: 749d181baf018ebe22406de71ae168853908a802 [file] [log] [blame]
Douglas Gregordd861062008-12-05 18:15:24 +00001//===------- SemaTemplate.cpp - Semantic Analysis for C++ Templates -------===/
2
3//
4// The LLVM Compiler Infrastructure
5//
6// This file is distributed under the University of Illinois Open Source
7// License. See LICENSE.TXT for details.
8//+//===----------------------------------------------------------------------===/
9
10//
11// This file implements semantic analysis for C++ templates.
12//+//===----------------------------------------------------------------------===/
13
14#include "Sema.h"
15#include "clang/Parse/DeclSpec.h"
16#include "clang/Basic/LangOptions.h"
17
18using namespace clang;
19
20/// isTemplateParameterDecl - Determines whether the given declaration
21/// 'D' names a template parameter.
22bool Sema::isTemplateParameterDecl(Decl *D) {
23 return isa<TemplateTypeParmDecl>(D) || isa<NonTypeTemplateParmDecl>(D);
24}
25
26/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
27/// that the template parameter 'PrevDecl' is being shadowed by a new
28/// declaration at location Loc. Returns true to indicate that this is
29/// an error, and false otherwise.
30bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) {
31 assert(isTemplateParameterDecl(PrevDecl) && "Not a template parameter");
32
33 // Microsoft Visual C++ permits template parameters to be shadowed.
34 if (getLangOptions().Microsoft)
35 return false;
36
37 // C++ [temp.local]p4:
38 // A template-parameter shall not be redeclared within its
39 // scope (including nested scopes).
40 Diag(Loc, diag::err_template_param_shadow)
41 << cast<NamedDecl>(PrevDecl)->getDeclName();
42 Diag(PrevDecl->getLocation(), diag::note_template_param_here);
43 return true;
44}
45
46/// ActOnTypeParameter - Called when a C++ template type parameter
47/// (e.g., "typename T") has been parsed. Typename specifies whether
48/// the keyword "typename" was used to declare the type parameter
49/// (otherwise, "class" was used), and KeyLoc is the location of the
50/// "class" or "typename" keyword. ParamName is the name of the
51/// parameter (NULL indicates an unnamed template parameter) and
52/// ParamName is the location of the parameter name (if any).
53/// If the type parameter has a default argument, it will be added
54/// later via ActOnTypeParameterDefault.
55Sema::DeclTy *Sema::ActOnTypeParameter(Scope *S, bool Typename,
56 SourceLocation KeyLoc,
57 IdentifierInfo *ParamName,
58 SourceLocation ParamNameLoc) {
59 assert(S->isTemplateParamScope() &&
60 "Template type parameter not in template parameter scope!");
61 bool Invalid = false;
62
63 if (ParamName) {
64 Decl *PrevDecl = LookupDecl(ParamName, Decl::IDNS_Tag, S);
65 if (PrevDecl && isTemplateParameterDecl(PrevDecl))
66 Invalid = Invalid || DiagnoseTemplateParameterShadow(ParamNameLoc,
67 PrevDecl);
68 }
69
70 TemplateTypeParmDecl *Param
71 = TemplateTypeParmDecl::Create(Context, CurContext,
72 ParamNameLoc, ParamName, Typename);
73 if (Invalid)
74 Param->setInvalidDecl();
75
76 if (ParamName) {
77 // Add the template parameter into the current scope.
78 S->AddDecl(Param);
79 IdResolver.AddDecl(Param);
80 }
81
82 return Param;
83}
84
85/// ActOnNonTypeTemplateParameter - Called when a C++ non-type
86/// template parameter (e.g., "int Size" in "template<int Size>
87/// class Array") has been parsed. S is the current scope and D is
88/// the parsed declarator.
89Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D) {
90 QualType T = GetTypeForDeclarator(D, S);
91
92 assert(S->isTemplateParamScope() &&
93 "Template type parameter not in template parameter scope!");
94 bool Invalid = false;
95
96 IdentifierInfo *ParamName = D.getIdentifier();
97 if (ParamName) {
98 Decl *PrevDecl = LookupDecl(ParamName, Decl::IDNS_Tag, S);
99 if (PrevDecl && isTemplateParameterDecl(PrevDecl))
100 Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
101 PrevDecl);
102 }
103
104 NonTypeTemplateParmDecl *Param
105 = NonTypeTemplateParmDecl::Create(Context, CurContext, D.getIdentifierLoc(),
106 ParamName, T);
107 if (Invalid)
108 Param->setInvalidDecl();
109
110 if (D.getIdentifier()) {
111 // Add the template parameter into the current scope.
112 S->AddDecl(Param);
113 IdResolver.AddDecl(Param);
114 }
115 return Param;
116}