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