NestedNameSpecifier.cpp revision 193326
1//===--- NestedNameSpecifier.cpp - C++ nested name specifiers -----*- C++ -*-=//
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 NestedNameSpecifier class, which represents
11//  a C++ nested-name-specifier.
12//
13//===----------------------------------------------------------------------===//
14#include "clang/AST/NestedNameSpecifier.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/PrettyPrinter.h"
18#include "clang/AST/Type.h"
19#include "llvm/Support/raw_ostream.h"
20#include <cassert>
21
22using namespace clang;
23
24NestedNameSpecifier *
25NestedNameSpecifier::FindOrInsert(ASTContext &Context,
26                                  const NestedNameSpecifier &Mockup) {
27  llvm::FoldingSetNodeID ID;
28  Mockup.Profile(ID);
29
30  void *InsertPos = 0;
31  NestedNameSpecifier *NNS
32    = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
33  if (!NNS) {
34    NNS = new (Context, 4) NestedNameSpecifier(Mockup);
35    Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
36  }
37
38  return NNS;
39}
40
41NestedNameSpecifier *
42NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix,
43                            IdentifierInfo *II) {
44  assert(II && "Identifier cannot be NULL");
45  assert(Prefix && Prefix->isDependent() && "Prefix must be dependent");
46
47  NestedNameSpecifier Mockup;
48  Mockup.Prefix.setPointer(Prefix);
49  Mockup.Prefix.setInt(Identifier);
50  Mockup.Specifier = II;
51  return FindOrInsert(Context, Mockup);
52}
53
54NestedNameSpecifier *
55NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix,
56                            NamespaceDecl *NS) {
57  assert(NS && "Namespace cannot be NULL");
58  assert((!Prefix ||
59          (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) &&
60         "Broken nested name specifier");
61  NestedNameSpecifier Mockup;
62  Mockup.Prefix.setPointer(Prefix);
63  Mockup.Prefix.setInt(Namespace);
64  Mockup.Specifier = NS;
65  return FindOrInsert(Context, Mockup);
66}
67
68NestedNameSpecifier *
69NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix,
70                            bool Template, Type *T) {
71  assert(T && "Type cannot be NULL");
72  NestedNameSpecifier Mockup;
73  Mockup.Prefix.setPointer(Prefix);
74  Mockup.Prefix.setInt(Template? TypeSpecWithTemplate : TypeSpec);
75  Mockup.Specifier = T;
76  return FindOrInsert(Context, Mockup);
77}
78
79NestedNameSpecifier *NestedNameSpecifier::GlobalSpecifier(ASTContext &Context) {
80  if (!Context.GlobalNestedNameSpecifier)
81    Context.GlobalNestedNameSpecifier = new (Context, 4) NestedNameSpecifier();
82  return Context.GlobalNestedNameSpecifier;
83}
84
85/// \brief Whether this nested name specifier refers to a dependent
86/// type or not.
87bool NestedNameSpecifier::isDependent() const {
88  switch (getKind()) {
89  case Identifier:
90    // Identifier specifiers always represent dependent types
91    return true;
92
93  case Namespace:
94  case Global:
95    return false;
96
97  case TypeSpec:
98  case TypeSpecWithTemplate:
99    return getAsType()->isDependentType();
100  }
101
102  // Necessary to suppress a GCC warning.
103  return false;
104}
105
106/// \brief Print this nested name specifier to the given output
107/// stream.
108void
109NestedNameSpecifier::print(llvm::raw_ostream &OS,
110                           const PrintingPolicy &Policy) const {
111  if (getPrefix())
112    getPrefix()->print(OS, Policy);
113
114  switch (getKind()) {
115  case Identifier:
116    OS << getAsIdentifier()->getName();
117    break;
118
119  case Namespace:
120    OS << getAsNamespace()->getIdentifier()->getName();
121    break;
122
123  case Global:
124    break;
125
126  case TypeSpecWithTemplate:
127    OS << "template ";
128    // Fall through to print the type.
129
130  case TypeSpec: {
131    std::string TypeStr;
132    Type *T = getAsType();
133
134    // If this is a qualified name type, suppress the qualification:
135    // it's part of our nested-name-specifier sequence anyway.  FIXME:
136    // We should be able to assert that this doesn't happen.
137    if (const QualifiedNameType *QualT = dyn_cast<QualifiedNameType>(T))
138      T = QualT->getNamedType().getTypePtr();
139
140    PrintingPolicy InnerPolicy(Policy);
141    InnerPolicy.SuppressTagKind = true;
142    T->getAsStringInternal(TypeStr, InnerPolicy);
143    OS << TypeStr;
144    break;
145  }
146  }
147
148  OS << "::";
149}
150
151void NestedNameSpecifier::Destroy(ASTContext &Context) {
152  this->~NestedNameSpecifier();
153  Context.Deallocate((void *)this);
154}
155
156void NestedNameSpecifier::dump() {
157  PrintingPolicy Policy;
158  Policy.CPlusPlus = true;
159  print(llvm::errs(), Policy);
160}
161