1 //===--- TemplateName.cpp - C++ Template Name Representation---------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file defines the TemplateName interface and subclasses.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/AST/TemplateName.h"
15 #include "clang/AST/DeclTemplate.h"
16 #include "clang/AST/NestedNameSpecifier.h"
17 #include "clang/AST/PrettyPrinter.h"
18 #include "clang/AST/TemplateBase.h"
19 #include "clang/Basic/Diagnostic.h"
20 #include "clang/Basic/LangOptions.h"
21 #include "llvm/Support/raw_ostream.h"
22 using namespace clang;
23 using namespace llvm;
24 
25 TemplateArgument
26 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
27   return TemplateArgument(Arguments, size());
28 }
29 
30 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
31   Profile(ID, Parameter, Replacement);
32 }
33 
34 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
35                                            TemplateTemplateParmDecl *parameter,
36                                                TemplateName replacement) {
37   ID.AddPointer(parameter);
38   ID.AddPointer(replacement.getAsVoidPointer());
39 }
40 
41 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
42                                                    ASTContext &Context) {
43   Profile(ID, Context, Parameter, TemplateArgument(Arguments, size()));
44 }
45 
46 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
47                                                    ASTContext &Context,
48                                            TemplateTemplateParmDecl *Parameter,
49                                              const TemplateArgument &ArgPack) {
50   ID.AddPointer(Parameter);
51   ArgPack.Profile(ID, Context);
52 }
53 
54 TemplateName::NameKind TemplateName::getKind() const {
55   if (Storage.is<TemplateDecl *>())
56     return Template;
57   if (Storage.is<DependentTemplateName *>())
58     return DependentTemplate;
59   if (Storage.is<QualifiedTemplateName *>())
60     return QualifiedTemplate;
61 
62   UncommonTemplateNameStorage *uncommon
63     = Storage.get<UncommonTemplateNameStorage*>();
64   if (uncommon->getAsOverloadedStorage())
65     return OverloadedTemplate;
66   if (uncommon->getAsSubstTemplateTemplateParm())
67     return SubstTemplateTemplateParm;
68   return SubstTemplateTemplateParmPack;
69 }
70 
71 TemplateDecl *TemplateName::getAsTemplateDecl() const {
72   if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
73     return Template;
74 
75   if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
76     return QTN->getTemplateDecl();
77 
78   if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
79     return sub->getReplacement().getAsTemplateDecl();
80 
81   return nullptr;
82 }
83 
84 bool TemplateName::isDependent() const {
85   if (TemplateDecl *Template = getAsTemplateDecl()) {
86     if (isa<TemplateTemplateParmDecl>(Template))
87       return true;
88     // FIXME: Hack, getDeclContext() can be null if Template is still
89     // initializing due to PCH reading, so we check it before using it.
90     // Should probably modify TemplateSpecializationType to allow constructing
91     // it without the isDependent() checking.
92     return Template->getDeclContext() &&
93            Template->getDeclContext()->isDependentContext();
94   }
95 
96   assert(!getAsOverloadedTemplate() &&
97          "overloaded templates shouldn't survive to here");
98 
99   return true;
100 }
101 
102 bool TemplateName::isInstantiationDependent() const {
103   if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
104     if (QTN->getQualifier()->isInstantiationDependent())
105       return true;
106   }
107 
108   return isDependent();
109 }
110 
111 bool TemplateName::containsUnexpandedParameterPack() const {
112   if (TemplateDecl *Template = getAsTemplateDecl()) {
113     if (TemplateTemplateParmDecl *TTP
114                                   = dyn_cast<TemplateTemplateParmDecl>(Template))
115       return TTP->isParameterPack();
116 
117     return false;
118   }
119 
120   if (DependentTemplateName *DTN = getAsDependentTemplateName())
121     return DTN->getQualifier() &&
122       DTN->getQualifier()->containsUnexpandedParameterPack();
123 
124   return getAsSubstTemplateTemplateParmPack() != nullptr;
125 }
126 
127 void
128 TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
129                     bool SuppressNNS) const {
130   if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
131     OS << *Template;
132   else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
133     if (!SuppressNNS)
134       QTN->getQualifier()->print(OS, Policy);
135     if (QTN->hasTemplateKeyword())
136       OS << "template ";
137     OS << *QTN->getDecl();
138   } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
139     if (!SuppressNNS && DTN->getQualifier())
140       DTN->getQualifier()->print(OS, Policy);
141     OS << "template ";
142 
143     if (DTN->isIdentifier())
144       OS << DTN->getIdentifier()->getName();
145     else
146       OS << "operator " << getOperatorSpelling(DTN->getOperator());
147   } else if (SubstTemplateTemplateParmStorage *subst
148                = getAsSubstTemplateTemplateParm()) {
149     subst->getReplacement().print(OS, Policy, SuppressNNS);
150   } else if (SubstTemplateTemplateParmPackStorage *SubstPack
151                                         = getAsSubstTemplateTemplateParmPack())
152     OS << *SubstPack->getParameterPack();
153   else {
154     OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
155     (*OTS->begin())->printName(OS);
156   }
157 }
158 
159 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
160                                            TemplateName N) {
161   std::string NameStr;
162   raw_string_ostream OS(NameStr);
163   LangOptions LO;
164   LO.CPlusPlus = true;
165   LO.Bool = true;
166   OS << '\'';
167   N.print(OS, PrintingPolicy(LO));
168   OS << '\'';
169   OS.flush();
170   return DB << NameStr;
171 }
172 
173 void TemplateName::dump(raw_ostream &OS) const {
174   LangOptions LO;  // FIXME!
175   LO.CPlusPlus = true;
176   LO.Bool = true;
177   print(OS, PrintingPolicy(LO));
178 }
179 
180 void TemplateName::dump() const {
181   dump(llvm::errs());
182 }
183