blob: 55c2e61ff09b36d9c0fd33e975b1a3a19cb70246 [file] [log] [blame]
Chris Lattner0ed844b2008-04-04 06:12:32 +00001//===-- DeclBase.h - Base Classes for representing declarations *- 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//
Chris Lattnerb048c982008-04-06 04:47:34 +000010// This file defines the Decl and DeclContext interfaces.
Chris Lattner0ed844b2008-04-04 06:12:32 +000011//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_DECLBASE_H
15#define LLVM_CLANG_AST_DECLBASE_H
16
17#include "clang/AST/Attr.h"
18#include "clang/AST/Type.h"
19#include "clang/Basic/SourceLocation.h"
20
21namespace clang {
Argyrios Kyrtzidisef177822008-04-17 14:40:12 +000022class TranslationUnitDecl;
Argyrios Kyrtzidis2d1c5d32008-04-27 13:50:30 +000023class NamespaceDecl;
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000024class ScopedDecl;
Chris Lattner0ed844b2008-04-04 06:12:32 +000025class FunctionDecl;
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000026class CXXRecordDecl;
Chris Lattnerb048c982008-04-06 04:47:34 +000027class EnumDecl;
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000028class ObjCMethodDecl;
Chris Lattner0ed844b2008-04-04 06:12:32 +000029class ObjCInterfaceDecl;
30
31/// Decl - This represents one declaration (or definition), e.g. a variable,
32/// typedef, function, struct, etc.
33///
34class Decl {
35public:
36 enum Kind {
37 // This lists the concrete classes of Decl in order of the inheritance
38 // hierarchy. This allows us to do efficient classof tests based on the
39 // enums below. The commented out names are abstract class names.
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000040 // [DeclContext] indicatea that the class also inherits from DeclContext.
Chris Lattner0ed844b2008-04-04 06:12:32 +000041
42 // Decl
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000043 TranslationUnit, // [DeclContext]
Chris Lattner0ed844b2008-04-04 06:12:32 +000044 // NamedDecl
45 Field,
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000046 CXXField,
Chris Lattner0ed844b2008-04-04 06:12:32 +000047 ObjCIvar,
48 ObjCCategory,
49 ObjCCategoryImpl,
50 ObjCImplementation,
51 ObjCProtocol,
Sam Bishop670aa9d2008-04-08 20:49:25 +000052 ObjCProperty,
Chris Lattner0ed844b2008-04-04 06:12:32 +000053 // ScopedDecl
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000054 Namespace, // [DeclContext]
Chris Lattner0ed844b2008-04-04 06:12:32 +000055 // TypeDecl
56 Typedef,
57 // TagDecl
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000058 Enum, // [DeclContext]
Chris Lattner0ed844b2008-04-04 06:12:32 +000059 // RecordDecl
60 Struct,
61 Union,
62 Class,
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000063 // CXXRecordDecl [DeclContext]
64 CXXStruct,
65 CXXUnion,
66 CXXClass,
Chris Lattner0ed844b2008-04-04 06:12:32 +000067 // ValueDecl
68 EnumConstant,
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000069 Function, // [DeclContext]
70 CXXMethod,
Steve Naroff248a7532008-04-15 22:42:06 +000071 Var,
Chris Lattner41110242008-06-17 18:05:57 +000072 ImplicitParam,
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000073 CXXClassVar,
Chris Lattner0ed844b2008-04-04 06:12:32 +000074 ParmVar,
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000075 ObjCInterface, // [DeclContext]
Chris Lattner0ed844b2008-04-04 06:12:32 +000076 ObjCCompatibleAlias,
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000077 ObjCMethod, // [DeclContext]
Chris Lattner0ed844b2008-04-04 06:12:32 +000078 ObjCClass,
79 ObjCForwardProtocol,
Fariborz Jahanian61d46152008-04-16 22:00:24 +000080 ObjCPropertyImpl,
Chris Lattner0ed844b2008-04-04 06:12:32 +000081 LinkageSpec,
82 FileScopeAsm,
83
84 // For each non-leaf class, we now define a mapping to the first/last member
85 // of the class, to allow efficient classof.
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +000086 NamedFirst = Field , NamedLast = ParmVar,
87 FieldFirst = Field , FieldLast = ObjCIvar,
88 ScopedFirst = Namespace , ScopedLast = ParmVar,
89 TypeFirst = Typedef , TypeLast = CXXClass,
90 TagFirst = Enum , TagLast = CXXClass,
91 RecordFirst = Struct , RecordLast = CXXClass,
92 CXXRecordFirst = CXXStruct , CXXRecordLast = CXXClass,
93 ValueFirst = EnumConstant , ValueLast = ParmVar,
94 FunctionFirst = Function , FunctionLast = CXXMethod,
95 VarFirst = Var , VarLast = ParmVar
Chris Lattner0ed844b2008-04-04 06:12:32 +000096 };
97
98 /// IdentifierNamespace - According to C99 6.2.3, there are four namespaces,
Douglas Gregor2ce52f32008-04-13 21:07:44 +000099 /// labels, tags, members and ordinary identifiers. These are meant
100 /// as bitmasks, so that searches in C++ can look into the "tag" namespace
101 /// during ordinary lookup.
Chris Lattner0ed844b2008-04-04 06:12:32 +0000102 enum IdentifierNamespace {
Douglas Gregor2ce52f32008-04-13 21:07:44 +0000103 IDNS_Label = 0x1,
104 IDNS_Tag = 0x2,
105 IDNS_Member = 0x4,
106 IDNS_Ordinary = 0x8
Chris Lattner0ed844b2008-04-04 06:12:32 +0000107 };
108
109 /// ObjCDeclQualifier - Qualifier used on types in method declarations
110 /// for remote messaging. They are meant for the arguments though and
111 /// applied to the Decls (ObjCMethodDecl and ParmVarDecl).
112 enum ObjCDeclQualifier {
113 OBJC_TQ_None = 0x0,
114 OBJC_TQ_In = 0x1,
115 OBJC_TQ_Inout = 0x2,
116 OBJC_TQ_Out = 0x4,
117 OBJC_TQ_Bycopy = 0x8,
118 OBJC_TQ_Byref = 0x10,
119 OBJC_TQ_Oneway = 0x20
120 };
121
122private:
123 /// Loc - The location that this decl.
124 SourceLocation Loc;
125
126 /// DeclKind - This indicates which class this is.
127 Kind DeclKind : 8;
128
129 /// InvalidDecl - This indicates a semantic error occurred.
130 unsigned int InvalidDecl : 1;
131
132 /// HasAttrs - This indicates whether the decl has attributes or not.
133 unsigned int HasAttrs : 1;
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000134
135 protected:
136 /// Access - Used by C++ decls for the access specifier.
137 // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
138 unsigned Access : 2;
139 friend class CXXClassMemberWrapper;
140
Chris Lattner0ed844b2008-04-04 06:12:32 +0000141 Decl(Kind DK, SourceLocation L) : Loc(L), DeclKind(DK), InvalidDecl(0),
142 HasAttrs(false) {
143 if (Decl::CollectingStats()) addDeclKind(DK);
144 }
Sam Bishop1bb19632008-04-11 18:04:39 +0000145
Chris Lattner0ed844b2008-04-04 06:12:32 +0000146 virtual ~Decl();
Sam Bishop1bb19632008-04-11 18:04:39 +0000147
148public:
Chris Lattner0ed844b2008-04-04 06:12:32 +0000149 SourceLocation getLocation() const { return Loc; }
150 void setLocation(SourceLocation L) { Loc = L; }
151
152 Kind getKind() const { return DeclKind; }
153 const char *getDeclKindName() const;
154
155 void addAttr(Attr *attr);
156 const Attr *getAttrs() const;
Chris Lattnera212c562008-05-04 02:29:49 +0000157 void swapAttrs(Decl *D);
Nuno Lopes9141bee2008-06-01 22:53:53 +0000158 void invalidateAttrs();
Chris Lattner0ed844b2008-04-04 06:12:32 +0000159
160 template<typename T> const T *getAttr() const {
161 for (const Attr *attr = getAttrs(); attr; attr = attr->getNext())
162 if (const T *V = dyn_cast<T>(attr))
163 return V;
164
165 return 0;
166 }
167
168 /// setInvalidDecl - Indicates the Decl had a semantic error. This
169 /// allows for graceful error recovery.
170 void setInvalidDecl() { InvalidDecl = 1; }
171 bool isInvalidDecl() const { return (bool) InvalidDecl; }
172
173 IdentifierNamespace getIdentifierNamespace() const {
174 switch (DeclKind) {
175 default: assert(0 && "Unknown decl kind!");
Chris Lattner41110242008-06-17 18:05:57 +0000176 case ImplicitParam:
Chris Lattner0ed844b2008-04-04 06:12:32 +0000177 case Typedef:
178 case Function:
Steve Naroff248a7532008-04-15 22:42:06 +0000179 case Var:
Chris Lattner0ed844b2008-04-04 06:12:32 +0000180 case ParmVar:
181 case EnumConstant:
182 case ObjCInterface:
183 case ObjCCompatibleAlias:
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000184 case CXXField:
Chris Lattner0ed844b2008-04-04 06:12:32 +0000185 return IDNS_Ordinary;
186 case Struct:
187 case Union:
188 case Class:
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000189 case CXXStruct:
190 case CXXUnion:
191 case CXXClass:
Chris Lattner0ed844b2008-04-04 06:12:32 +0000192 case Enum:
193 return IDNS_Tag;
Argyrios Kyrtzidis2d1c5d32008-04-27 13:50:30 +0000194 case Namespace:
195 return IdentifierNamespace(IDNS_Tag | IDNS_Ordinary);
Chris Lattner0ed844b2008-04-04 06:12:32 +0000196 }
197 }
198 // global temp stats (until we have a per-module visitor)
199 static void addDeclKind(Kind k);
200 static bool CollectingStats(bool Enable = false);
201 static void PrintStats();
202
203 // Implement isa/cast/dyncast/etc.
204 static bool classof(const Decl *) { return true; }
205
206 /// Emit - Serialize this Decl to Bitcode.
207 void Emit(llvm::Serializer& S) const;
208
209 /// Create - Deserialize a Decl from Bitcode.
Sam Bishope2563ca2008-04-07 21:55:54 +0000210 static Decl* Create(llvm::Deserializer& D, ASTContext& C);
Chris Lattner0ed844b2008-04-04 06:12:32 +0000211
Sam Bishopbb45c512008-04-11 15:01:25 +0000212 /// Destroy - Call destructors and release memory.
Ted Kremenek27f8a282008-05-20 00:43:19 +0000213 virtual void Destroy(ASTContext& C);
Sam Bishopbb45c512008-04-11 15:01:25 +0000214
Chris Lattner0ed844b2008-04-04 06:12:32 +0000215protected:
216 /// EmitImpl - Provides the subclass-specific serialization logic for
217 /// serializing out a decl.
218 virtual void EmitImpl(llvm::Serializer& S) const {
219 // FIXME: This will eventually be a pure virtual function.
220 assert (false && "Not implemented.");
221 }
222
223 void EmitInRec(llvm::Serializer& S) const;
Sam Bishope2563ca2008-04-07 21:55:54 +0000224 void ReadInRec(llvm::Deserializer& D, ASTContext& C);
Chris Lattner0ed844b2008-04-04 06:12:32 +0000225};
226
Chris Lattnerb048c982008-04-06 04:47:34 +0000227/// DeclContext - This is used only as base class of specific decl types that
Chris Lattner0ed844b2008-04-04 06:12:32 +0000228/// can act as declaration contexts. These decls are:
229///
Argyrios Kyrtzidisef177822008-04-17 14:40:12 +0000230/// TranslationUnitDecl
Argyrios Kyrtzidis2d1c5d32008-04-27 13:50:30 +0000231/// NamespaceDecl
Chris Lattner0ed844b2008-04-04 06:12:32 +0000232/// FunctionDecl
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000233/// CXXRecordDecl
Chris Lattnerb048c982008-04-06 04:47:34 +0000234/// EnumDecl
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000235/// ObjCMethodDecl
Chris Lattner0ed844b2008-04-04 06:12:32 +0000236/// ObjCInterfaceDecl
237///
Chris Lattnerb048c982008-04-06 04:47:34 +0000238class DeclContext {
Chris Lattner0ed844b2008-04-04 06:12:32 +0000239 /// DeclKind - This indicates which class this is.
240 Decl::Kind DeclKind : 8;
241
Argyrios Kyrtzidis76435362008-06-10 01:32:09 +0000242 /// DeclChain - Linked list of declarations that are defined inside this
243 /// declaration context.
244 ScopedDecl *DeclChain;
245
Chris Lattner0ed844b2008-04-04 06:12:32 +0000246 // Used in the CastTo template to get the DeclKind
Chris Lattnerb048c982008-04-06 04:47:34 +0000247 // from a Decl or a DeclContext. DeclContext doesn't have a getKind() method
Chris Lattner0ed844b2008-04-04 06:12:32 +0000248 // to avoid 'ambiguous access' compiler errors.
249 template<typename T> struct KindTrait {
250 static Decl::Kind getKind(const T *D) { return D->getKind(); }
251 };
252
253 // Used only by the ToDecl and FromDecl methods
254 template<typename To, typename From>
255 static To *CastTo(const From *D) {
256 Decl::Kind DK = KindTrait<From>::getKind(D);
257 switch(DK) {
Argyrios Kyrtzidisef177822008-04-17 14:40:12 +0000258 case Decl::TranslationUnit:
259 return static_cast<TranslationUnitDecl*>(const_cast<From*>(D));
Argyrios Kyrtzidis2d1c5d32008-04-27 13:50:30 +0000260 case Decl::Namespace:
261 return static_cast<NamespaceDecl*>(const_cast<From*>(D));
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000262 case Decl::Enum:
263 return static_cast<EnumDecl*>(const_cast<From*>(D));
Chris Lattner0ed844b2008-04-04 06:12:32 +0000264 case Decl::ObjCMethod:
265 return static_cast<ObjCMethodDecl*>(const_cast<From*>(D));
266 case Decl::ObjCInterface:
267 return static_cast<ObjCInterfaceDecl*>(const_cast<From*>(D));
268 default:
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000269 if (DK >= Decl::FunctionFirst && DK <= Decl::FunctionLast)
270 return static_cast<FunctionDecl*>(const_cast<From*>(D));
271 if (DK >= Decl::CXXRecordFirst && DK <= Decl::CXXRecordLast)
272 return static_cast<CXXRecordDecl*>(const_cast<From*>(D));
273
Chris Lattnerb048c982008-04-06 04:47:34 +0000274 assert(false && "a decl that inherits DeclContext isn't handled");
Chris Lattner0ed844b2008-04-04 06:12:32 +0000275 return 0;
276 }
277 }
278
279protected:
Argyrios Kyrtzidis76435362008-06-10 01:32:09 +0000280 DeclContext(Decl::Kind K) : DeclKind(K), DeclChain(0) {}
Chris Lattner0ed844b2008-04-04 06:12:32 +0000281
282public:
Chris Lattnerb048c982008-04-06 04:47:34 +0000283 /// getParent - Returns the containing DeclContext if this is a ScopedDecl,
Chris Lattner0ed844b2008-04-04 06:12:32 +0000284 /// else returns NULL.
Chris Lattnerb048c982008-04-06 04:47:34 +0000285 DeclContext *getParent() const;
Chris Lattner0ed844b2008-04-04 06:12:32 +0000286
287 bool isFunctionOrMethod() const {
288 switch (DeclKind) {
289 case Decl::Function:
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000290 case Decl::CXXMethod:
Chris Lattner0ed844b2008-04-04 06:12:32 +0000291 case Decl::ObjCMethod:
292 return true;
293 default:
294 return false;
295 }
296 }
297
Argyrios Kyrtzidis76435362008-06-10 01:32:09 +0000298 ScopedDecl *getDeclChain() const { return DeclChain; }
299 void setDeclChain(ScopedDecl *D) { DeclChain = D; }
300
Chris Lattnerb048c982008-04-06 04:47:34 +0000301 /// ToDecl and FromDecl make Decl <-> DeclContext castings.
Chris Lattner0ed844b2008-04-04 06:12:32 +0000302 /// They are intended to be used by the simplify_type and cast_convert_val
303 /// templates.
Chris Lattnerb048c982008-04-06 04:47:34 +0000304 static Decl *ToDecl (const DeclContext *D);
305 static DeclContext *FromDecl (const Decl *D);
Chris Lattner0ed844b2008-04-04 06:12:32 +0000306
307 static bool classof(const Decl *D) {
308 switch (D->getKind()) {
Argyrios Kyrtzidisef177822008-04-17 14:40:12 +0000309 case Decl::TranslationUnit:
Argyrios Kyrtzidis2d1c5d32008-04-27 13:50:30 +0000310 case Decl::Namespace:
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000311 case Decl::Enum:
Chris Lattner0ed844b2008-04-04 06:12:32 +0000312 case Decl::ObjCMethod:
313 case Decl::ObjCInterface:
314 return true;
315 default:
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000316 if (D->getKind() >= Decl::FunctionFirst &&
317 D->getKind() <= Decl::FunctionLast)
318 return true;
319 if (D->getKind() >= Decl::CXXRecordFirst &&
320 D->getKind() <= Decl::CXXRecordLast)
321 return true;
Chris Lattnerb048c982008-04-06 04:47:34 +0000322 return false;
Chris Lattner0ed844b2008-04-04 06:12:32 +0000323 }
324 }
Chris Lattnerb048c982008-04-06 04:47:34 +0000325 static bool classof(const DeclContext *D) { return true; }
Argyrios Kyrtzidisef177822008-04-17 14:40:12 +0000326 static bool classof(const TranslationUnitDecl *D) { return true; }
Argyrios Kyrtzidis2d1c5d32008-04-27 13:50:30 +0000327 static bool classof(const NamespaceDecl *D) { return true; }
Chris Lattner0ed844b2008-04-04 06:12:32 +0000328 static bool classof(const FunctionDecl *D) { return true; }
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000329 static bool classof(const CXXRecordDecl *D) { return true; }
Chris Lattnerb048c982008-04-06 04:47:34 +0000330 static bool classof(const EnumDecl *D) { return true; }
Argyrios Kyrtzidisd3bb44f2008-06-09 21:05:31 +0000331 static bool classof(const ObjCMethodDecl *D) { return true; }
Chris Lattner0ed844b2008-04-04 06:12:32 +0000332 static bool classof(const ObjCInterfaceDecl *D) { return true; }
Argyrios Kyrtzidis76435362008-06-10 01:32:09 +0000333
334private:
335 void EmitOutRec(llvm::Serializer& S) const;
336 void ReadOutRec(llvm::Deserializer& D, ASTContext& C);
337
338 friend class Decl;
Chris Lattner0ed844b2008-04-04 06:12:32 +0000339};
340
Chris Lattnerb048c982008-04-06 04:47:34 +0000341template<> struct DeclContext::KindTrait<DeclContext> {
342 static Decl::Kind getKind(const DeclContext *D) { return D->DeclKind; }
Chris Lattner0ed844b2008-04-04 06:12:32 +0000343};
344
345} // end clang.
346
347namespace llvm {
Chris Lattnerb048c982008-04-06 04:47:34 +0000348/// Implement simplify_type for DeclContext, so that we can dyn_cast from
349/// DeclContext to a specific Decl class.
350 template<> struct simplify_type<const ::clang::DeclContext*> {
Chris Lattner0ed844b2008-04-04 06:12:32 +0000351 typedef ::clang::Decl* SimpleType;
Chris Lattnerb048c982008-04-06 04:47:34 +0000352 static SimpleType getSimplifiedValue(const ::clang::DeclContext *Val) {
353 return ::clang::DeclContext::ToDecl(Val);
Chris Lattner0ed844b2008-04-04 06:12:32 +0000354 }
355};
Chris Lattnerb048c982008-04-06 04:47:34 +0000356template<> struct simplify_type< ::clang::DeclContext*>
357 : public simplify_type<const ::clang::DeclContext*> {};
Chris Lattner0ed844b2008-04-04 06:12:32 +0000358
Chris Lattnerb048c982008-04-06 04:47:34 +0000359template<> struct simplify_type<const ::clang::DeclContext> {
Chris Lattner0ed844b2008-04-04 06:12:32 +0000360 typedef ::clang::Decl SimpleType;
Chris Lattnerb048c982008-04-06 04:47:34 +0000361 static SimpleType &getSimplifiedValue(const ::clang::DeclContext &Val) {
362 return *::clang::DeclContext::ToDecl(&Val);
Chris Lattner0ed844b2008-04-04 06:12:32 +0000363 }
364};
Chris Lattnerb048c982008-04-06 04:47:34 +0000365template<> struct simplify_type< ::clang::DeclContext>
366 : public simplify_type<const ::clang::DeclContext> {};
Chris Lattner0ed844b2008-04-04 06:12:32 +0000367
Chris Lattnerb048c982008-04-06 04:47:34 +0000368/// Implement cast_convert_val for DeclContext, so that we can dyn_cast from
369/// a Decl class to DeclContext.
Chris Lattner0ed844b2008-04-04 06:12:32 +0000370template<class FromTy>
Chris Lattnerb048c982008-04-06 04:47:34 +0000371struct cast_convert_val< ::clang::DeclContext,const FromTy,const FromTy> {
372 static ::clang::DeclContext &doit(const FromTy &Val) {
373 return *::clang::DeclContext::FromDecl(&Val);
Chris Lattner0ed844b2008-04-04 06:12:32 +0000374 }
375};
376template<class FromTy>
Chris Lattnerb048c982008-04-06 04:47:34 +0000377struct cast_convert_val< ::clang::DeclContext,FromTy,FromTy>
378 : public cast_convert_val< ::clang::DeclContext,const FromTy,const FromTy>
Chris Lattner0ed844b2008-04-04 06:12:32 +0000379 {};
380
381template<class FromTy>
Chris Lattnerb048c982008-04-06 04:47:34 +0000382struct cast_convert_val< ::clang::DeclContext,const FromTy*,const FromTy*> {
383 static ::clang::DeclContext *doit(const FromTy *Val) {
384 return ::clang::DeclContext::FromDecl(Val);
Chris Lattner0ed844b2008-04-04 06:12:32 +0000385 }
386};
387template<class FromTy>
Chris Lattnerb048c982008-04-06 04:47:34 +0000388struct cast_convert_val< ::clang::DeclContext,FromTy*,FromTy*>
389 : public cast_convert_val< ::clang::DeclContext,const FromTy*,const FromTy*>
Chris Lattner0ed844b2008-04-04 06:12:32 +0000390 {};
391
392} // end namespace llvm
393
394#endif