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