NestedNameSpecifier.cpp revision d57959af02b4af695276f4204443afe6e5d86bd8
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/Type.h"
18#include "llvm/Support/raw_ostream.h"
19#include <cassert>
20#include <stdio.h>
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) 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 = Prefix;
49  Mockup.Specifier.setPointer(II);
50  Mockup.Specifier.setInt(Identifier);
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 = Prefix;
63  Mockup.Specifier.setPointer(NS);
64  Mockup.Specifier.setInt(Namespace);
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 = Prefix;
74  Mockup.Specifier.setPointer(T);
75  Mockup.Specifier.setInt(Template? TypeSpecWithTemplate : TypeSpec);
76  return FindOrInsert(Context, Mockup);
77}
78
79NestedNameSpecifier *NestedNameSpecifier::GlobalSpecifier(ASTContext &Context) {
80  if (!Context.GlobalNestedNameSpecifier)
81    Context.GlobalNestedNameSpecifier = new (Context) 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 NestedNameSpecifier::Print(llvm::raw_ostream &OS) const {
109  if (Prefix)
110    Prefix->Print(OS);
111
112  switch (getKind()) {
113  case Identifier:
114    OS << getAsIdentifier()->getName();
115    break;
116
117  case Namespace:
118    OS << getAsNamespace()->getIdentifier()->getName();
119    break;
120
121  case Global:
122    break;
123
124  case TypeSpecWithTemplate:
125    OS << "template ";
126    // Fall through to print the type.
127
128  case TypeSpec: {
129    std::string TypeStr;
130    Type *T = getAsType();
131
132    // If this is a qualified name type, suppress the qualification:
133    // it's part of our nested-name-specifier sequence anyway.  FIXME:
134    // We should be able to assert that this doesn't happen.
135    if (const QualifiedNameType *QualT = dyn_cast<QualifiedNameType>(T))
136      T = QualT->getNamedType().getTypePtr();
137
138    if (const TagType *TagT = dyn_cast<TagType>(T))
139      TagT->getAsStringInternal(TypeStr, true);
140    else
141      T->getAsStringInternal(TypeStr);
142    OS << TypeStr;
143    break;
144  }
145  }
146
147  OS << "::";
148}
149
150void NestedNameSpecifier::Destroy(ASTContext &Context) {
151  this->~NestedNameSpecifier();
152  Context.Deallocate((void *)this);
153}
154
155void NestedNameSpecifier::Dump() {
156  std::string Result;
157  {
158    llvm::raw_string_ostream OS(Result);
159    Print(OS);
160  }
161  fprintf(stderr, "%s", Result.c_str());
162}
163