blob: 62e972efd5704a26ba416a97e86c80c821c148b4 [file] [log] [blame]
Douglas Gregore4e5b052009-03-19 00:18:19 +00001//===--- 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"
Douglas Gregorbad35182009-03-19 03:51:16 +000018#include "llvm/Support/raw_ostream.h"
Douglas Gregorab452ba2009-03-26 23:50:42 +000019#include <cassert>
Douglas Gregorbad35182009-03-19 03:51:16 +000020
Douglas Gregore4e5b052009-03-19 00:18:19 +000021using namespace clang;
22
Douglas Gregorab452ba2009-03-26 23:50:42 +000023NestedNameSpecifier *
24NestedNameSpecifier::FindOrInsert(ASTContext &Context,
25 const NestedNameSpecifier &Mockup) {
26 llvm::FoldingSetNodeID ID;
27 Mockup.Profile(ID);
Douglas Gregore4e5b052009-03-19 00:18:19 +000028
Douglas Gregorab452ba2009-03-26 23:50:42 +000029 void *InsertPos = 0;
30 NestedNameSpecifier *NNS
31 = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
32 if (!NNS) {
33 NNS = new (Context) NestedNameSpecifier(Mockup);
34 Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
35 }
Douglas Gregore4e5b052009-03-19 00:18:19 +000036
Douglas Gregorab452ba2009-03-26 23:50:42 +000037 return NNS;
Douglas Gregore4e5b052009-03-19 00:18:19 +000038}
Douglas Gregorbad35182009-03-19 03:51:16 +000039
Douglas Gregorab452ba2009-03-26 23:50:42 +000040NestedNameSpecifier *
41NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix,
42 IdentifierInfo *II) {
43 assert(II && "Identifier cannot be NULL");
44 assert(Prefix && Prefix->isDependent() && "Prefix must be dependent");
Douglas Gregorbad35182009-03-19 03:51:16 +000045
Douglas Gregorab452ba2009-03-26 23:50:42 +000046 NestedNameSpecifier Mockup;
47 Mockup.Prefix = Prefix;
48 Mockup.Specifier.setPointer(II);
49 Mockup.Specifier.setInt(Identifier);
50 return FindOrInsert(Context, Mockup);
51}
Douglas Gregorbad35182009-03-19 03:51:16 +000052
Douglas Gregorab452ba2009-03-26 23:50:42 +000053NestedNameSpecifier *
54NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix,
55 NamespaceDecl *NS) {
56 assert(NS && "Namespace cannot be NULL");
57 assert((!Prefix ||
58 (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) &&
59 "Broken nested name specifier");
60 NestedNameSpecifier Mockup;
61 Mockup.Prefix = Prefix;
62 Mockup.Specifier.setPointer(NS);
63 Mockup.Specifier.setInt(Namespace);
64 return FindOrInsert(Context, Mockup);
65}
66
67NestedNameSpecifier *
68NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix,
69 bool Template, Type *T) {
70 assert(T && "Type cannot be NULL");
71 NestedNameSpecifier Mockup;
72 Mockup.Prefix = Prefix;
73 Mockup.Specifier.setPointer(T);
74 Mockup.Specifier.setInt(Template? TypeSpecWithTemplate : TypeSpec);
75 return FindOrInsert(Context, Mockup);
76}
Douglas Gregorbad35182009-03-19 03:51:16 +000077
Douglas Gregorab452ba2009-03-26 23:50:42 +000078NestedNameSpecifier *NestedNameSpecifier::GlobalSpecifier(ASTContext &Context) {
79 if (!Context.GlobalNestedNameSpecifier)
80 Context.GlobalNestedNameSpecifier = new (Context) NestedNameSpecifier();
81 return Context.GlobalNestedNameSpecifier;
82}
83
84/// \brief Whether this nested name specifier refers to a dependent
85/// type or not.
86bool NestedNameSpecifier::isDependent() const {
87 switch (getKind()) {
88 case Identifier:
89 // Identifier specifiers always represent dependent types
90 return true;
91
92 case Namespace:
93 case Global:
94 return false;
95
96 case TypeSpec:
97 case TypeSpecWithTemplate:
98 return getAsType()->isDependentType();
Douglas Gregorbad35182009-03-19 03:51:16 +000099 }
Douglas Gregorab452ba2009-03-26 23:50:42 +0000100
101 // Necessary to suppress a GCC warning.
102 return false;
103}
104
105/// \brief Print this nested name specifier to the given output
106/// stream.
107void NestedNameSpecifier::Print(llvm::raw_ostream &OS) const {
108 if (Prefix)
109 Prefix->Print(OS);
110
111 switch (getKind()) {
112 case Identifier:
113 OS << getAsIdentifier()->getName();
114 break;
115
116 case Namespace:
117 OS << getAsNamespace()->getIdentifier()->getName();
118 break;
119
120 case Global:
121 break;
122
123 case TypeSpecWithTemplate:
124 OS << "template ";
125 // Fall through to print the type.
126
127 case TypeSpec: {
128 std::string TypeStr;
129 Type *T = getAsType();
130
131 // If this is a qualified name type, suppress the qualification:
132 // it's part of our nested-name-specifier sequence anyway. FIXME:
133 // We should be able to assert that this doesn't happen.
134 if (const QualifiedNameType *QualT = dyn_cast<QualifiedNameType>(T))
135 T = QualT->getNamedType().getTypePtr();
136
137 if (const TagType *TagT = dyn_cast<TagType>(T))
138 TagT->getAsStringInternal(TypeStr, true);
139 else
140 T->getAsStringInternal(TypeStr);
141 OS << TypeStr;
142 break;
143 }
144 }
145
146 OS << "::";
147}
148
149void NestedNameSpecifier::Destroy(ASTContext &Context) {
150 this->~NestedNameSpecifier();
151 Context.Deallocate((void *)this);
Douglas Gregorbad35182009-03-19 03:51:16 +0000152}