blob: f21d90f7c8c94b84ab4941a5a8d789391669afd7 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- SemaDeclSpec.cpp - Declaration Specifier Semantic Analysis -------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner0bc735f2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer5f016e22007-07-11 17:01:13 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements semantic analysis for declaration specifiers.
11//
12//===----------------------------------------------------------------------===//
13
John McCall19510852010-08-20 18:27:03 +000014#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
15#include "clang/Sema/DeclSpec.h"
16#include "clang/Sema/ParsedTemplate.h"
Douglas Gregor2e4c34a2011-02-24 00:17:56 +000017#include "clang/AST/NestedNameSpecifier.h"
18#include "clang/AST/TypeLoc.h"
Douglas Gregor9b3064b2009-04-01 22:41:11 +000019#include "clang/Lex/Preprocessor.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000020#include "clang/Basic/LangOptions.h"
Chris Lattner5af2f352009-01-20 19:11:22 +000021#include "llvm/ADT/STLExtras.h"
John McCall32d335e2009-08-03 18:47:27 +000022#include "llvm/Support/ErrorHandling.h"
Douglas Gregore4e5b052009-03-19 00:18:19 +000023#include <cstring>
Reid Spencer5f016e22007-07-11 17:01:13 +000024using namespace clang;
25
Chris Lattner254be6a2008-11-22 08:32:36 +000026
27static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc,
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +000028 unsigned DiagID) {
29 return D.Report(Loc, DiagID);
Chris Lattner254be6a2008-11-22 08:32:36 +000030}
31
Douglas Gregor314b97f2009-11-10 19:49:08 +000032
33void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
34 assert(TemplateId && "NULL template-id annotation?");
35 Kind = IK_TemplateId;
36 this->TemplateId = TemplateId;
37 StartLocation = TemplateId->TemplateNameLoc;
38 EndLocation = TemplateId->RAngleLoc;
39}
40
Douglas Gregor0efc2c12010-01-13 17:31:36 +000041void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
42 assert(TemplateId && "NULL template-id annotation?");
43 Kind = IK_ConstructorTemplateId;
44 this->TemplateId = TemplateId;
45 StartLocation = TemplateId->TemplateNameLoc;
46 EndLocation = TemplateId->RAngleLoc;
47}
48
Douglas Gregor2e4c34a2011-02-24 00:17:56 +000049void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc,
50 TypeLoc TL, SourceLocation ColonColonLoc) {
51 ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep,
52 TemplateKWLoc.isValid(),
53 TL.getTypePtr());
54 if (Range.getBegin().isInvalid())
55 Range.setBegin(TL.getBeginLoc());
56 Range.setEnd(ColonColonLoc);
57}
58
59void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier,
60 SourceLocation IdentifierLoc,
61 SourceLocation ColonColonLoc) {
62 ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Identifier);
63 if (Range.getBegin().isInvalid())
64 Range.setBegin(IdentifierLoc);
65 Range.setEnd(ColonColonLoc);
66}
67
68void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace,
69 SourceLocation NamespaceLoc,
70 SourceLocation ColonColonLoc) {
71 ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Namespace);
72 if (Range.getBegin().isInvalid())
73 Range.setBegin(NamespaceLoc);
74 Range.setEnd(ColonColonLoc);
75}
76
Douglas Gregor14aba762011-02-24 02:36:08 +000077void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
78 SourceLocation AliasLoc,
79 SourceLocation ColonColonLoc) {
80 ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Alias);
81 if (Range.getBegin().isInvalid())
82 Range.setBegin(AliasLoc);
83 Range.setEnd(ColonColonLoc);
84}
85
Douglas Gregor2e4c34a2011-02-24 00:17:56 +000086void CXXScopeSpec::MakeGlobal(ASTContext &Context,
87 SourceLocation ColonColonLoc) {
88 assert(!ScopeRep && "Already have a nested-name-specifier!?");
89 ScopeRep = NestedNameSpecifier::GlobalSpecifier(Context);
90 Range = SourceRange(ColonColonLoc);
91}
92
Chris Lattner5af2f352009-01-20 19:11:22 +000093/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
94/// "TheDeclarator" is the declarator that this will be added to.
John McCall7f040a92010-12-24 02:08:15 +000095DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs,
96 bool hasProto, bool isVariadic,
Douglas Gregor965acbb2009-02-18 07:07:28 +000097 SourceLocation EllipsisLoc,
Chris Lattner5af2f352009-01-20 19:11:22 +000098 ParamInfo *ArgInfo,
99 unsigned NumArgs,
100 unsigned TypeQuals,
Douglas Gregor83f51722011-01-26 03:43:54 +0000101 bool RefQualifierIsLvalueRef,
102 SourceLocation RefQualifierLoc,
Sebastian Redl7dc81342009-04-29 17:30:04 +0000103 bool hasExceptionSpec,
Sebastian Redl3cc97262009-05-31 11:47:27 +0000104 SourceLocation ThrowLoc,
Sebastian Redl7dc81342009-04-29 17:30:04 +0000105 bool hasAnyExceptionSpec,
John McCallb3d87482010-08-24 05:47:05 +0000106 ParsedType *Exceptions,
Sebastian Redlef65f062009-05-29 18:02:33 +0000107 SourceRange *ExceptionRanges,
Sebastian Redl7dc81342009-04-29 17:30:04 +0000108 unsigned NumExceptions,
Argyrios Kyrtzidis82bf0102009-08-19 23:14:54 +0000109 SourceLocation LPLoc,
110 SourceLocation RPLoc,
Douglas Gregordab60ad2010-10-01 18:44:50 +0000111 Declarator &TheDeclarator,
112 ParsedType TrailingReturnType) {
Chris Lattner5af2f352009-01-20 19:11:22 +0000113 DeclaratorChunk I;
Sebastian Redl7dc81342009-04-29 17:30:04 +0000114 I.Kind = Function;
Argyrios Kyrtzidis82bf0102009-08-19 23:14:54 +0000115 I.Loc = LPLoc;
116 I.EndLoc = RPLoc;
John McCall7f040a92010-12-24 02:08:15 +0000117 I.Fun.AttrList = attrs.getList();
Sebastian Redl7dc81342009-04-29 17:30:04 +0000118 I.Fun.hasPrototype = hasProto;
119 I.Fun.isVariadic = isVariadic;
120 I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
121 I.Fun.DeleteArgInfo = false;
122 I.Fun.TypeQuals = TypeQuals;
123 I.Fun.NumArgs = NumArgs;
124 I.Fun.ArgInfo = 0;
Douglas Gregor83f51722011-01-26 03:43:54 +0000125 I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef;
126 I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
Sebastian Redl7dc81342009-04-29 17:30:04 +0000127 I.Fun.hasExceptionSpec = hasExceptionSpec;
Sebastian Redl3cc97262009-05-31 11:47:27 +0000128 I.Fun.ThrowLoc = ThrowLoc.getRawEncoding();
Sebastian Redl7dc81342009-04-29 17:30:04 +0000129 I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec;
130 I.Fun.NumExceptions = NumExceptions;
131 I.Fun.Exceptions = 0;
Douglas Gregordab60ad2010-10-01 18:44:50 +0000132 I.Fun.TrailingReturnType = TrailingReturnType.getAsOpaquePtr();
Sebastian Redl7dc81342009-04-29 17:30:04 +0000133
Chris Lattner5af2f352009-01-20 19:11:22 +0000134 // new[] an argument array if needed.
135 if (NumArgs) {
136 // If the 'InlineParams' in Declarator is unused and big enough, put our
137 // parameter list there (in an effort to avoid new/delete traffic). If it
138 // is already used (consider a function returning a function pointer) or too
139 // small (function taking too many arguments), go to the heap.
Mike Stump1eb44332009-09-09 15:08:12 +0000140 if (!TheDeclarator.InlineParamsUsed &&
Chris Lattner5af2f352009-01-20 19:11:22 +0000141 NumArgs <= llvm::array_lengthof(TheDeclarator.InlineParams)) {
142 I.Fun.ArgInfo = TheDeclarator.InlineParams;
143 I.Fun.DeleteArgInfo = false;
144 TheDeclarator.InlineParamsUsed = true;
145 } else {
146 I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs];
147 I.Fun.DeleteArgInfo = true;
148 }
149 memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
150 }
Sebastian Redl7dc81342009-04-29 17:30:04 +0000151 // new[] an exception array if needed
152 if (NumExceptions) {
Sebastian Redlef65f062009-05-29 18:02:33 +0000153 I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions];
154 for (unsigned i = 0; i != NumExceptions; ++i) {
155 I.Fun.Exceptions[i].Ty = Exceptions[i];
156 I.Fun.Exceptions[i].Range = ExceptionRanges[i];
157 }
Sebastian Redl7dc81342009-04-29 17:30:04 +0000158 }
Chris Lattner5af2f352009-01-20 19:11:22 +0000159 return I;
160}
Chris Lattner254be6a2008-11-22 08:32:36 +0000161
Reid Spencer5f016e22007-07-11 17:01:13 +0000162/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
Chris Lattner2a327d12009-02-27 18:35:46 +0000163/// declaration specifier includes.
Reid Spencer5f016e22007-07-11 17:01:13 +0000164///
165unsigned DeclSpec::getParsedSpecifiers() const {
166 unsigned Res = 0;
167 if (StorageClassSpec != SCS_unspecified ||
168 SCS_thread_specified)
169 Res |= PQ_StorageClassSpecifier;
Mike Stumpd4204332008-06-19 19:52:46 +0000170
Reid Spencer5f016e22007-07-11 17:01:13 +0000171 if (TypeQualifiers != TQ_unspecified)
172 Res |= PQ_TypeQualifier;
Mike Stump1eb44332009-09-09 15:08:12 +0000173
Reid Spencer5f016e22007-07-11 17:01:13 +0000174 if (hasTypeSpecifier())
175 Res |= PQ_TypeSpecifier;
Mike Stump1eb44332009-09-09 15:08:12 +0000176
Douglas Gregorb48fe382008-10-31 09:07:45 +0000177 if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified)
Reid Spencer5f016e22007-07-11 17:01:13 +0000178 Res |= PQ_FunctionSpecifier;
179 return Res;
180}
181
John McCallfec54012009-08-03 20:12:06 +0000182template <class T> static bool BadSpecifier(T TNew, T TPrev,
183 const char *&PrevSpec,
184 unsigned &DiagID) {
John McCall32d335e2009-08-03 18:47:27 +0000185 PrevSpec = DeclSpec::getSpecifierName(TPrev);
John McCallfec54012009-08-03 20:12:06 +0000186 DiagID = (TNew == TPrev ? diag::ext_duplicate_declspec
187 : diag::err_invalid_decl_spec_combination);
John McCall32d335e2009-08-03 18:47:27 +0000188 return true;
Mike Stump1eb44332009-09-09 15:08:12 +0000189}
John McCall32d335e2009-08-03 18:47:27 +0000190
Reid Spencer5f016e22007-07-11 17:01:13 +0000191const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) {
192 switch (S) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000193 case DeclSpec::SCS_unspecified: return "unspecified";
194 case DeclSpec::SCS_typedef: return "typedef";
195 case DeclSpec::SCS_extern: return "extern";
196 case DeclSpec::SCS_static: return "static";
197 case DeclSpec::SCS_auto: return "auto";
198 case DeclSpec::SCS_register: return "register";
Eli Friedman63054b32009-04-19 20:27:55 +0000199 case DeclSpec::SCS_private_extern: return "__private_extern__";
Sebastian Redl669d5d72008-11-14 23:42:31 +0000200 case DeclSpec::SCS_mutable: return "mutable";
Reid Spencer5f016e22007-07-11 17:01:13 +0000201 }
Jeffrey Yasskin9f61aa92009-12-12 05:05:38 +0000202 llvm_unreachable("Unknown typespec!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000203}
204
John McCall32d335e2009-08-03 18:47:27 +0000205const char *DeclSpec::getSpecifierName(TSW W) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000206 switch (W) {
John McCall32d335e2009-08-03 18:47:27 +0000207 case TSW_unspecified: return "unspecified";
208 case TSW_short: return "short";
209 case TSW_long: return "long";
210 case TSW_longlong: return "long long";
Reid Spencer5f016e22007-07-11 17:01:13 +0000211 }
Jeffrey Yasskin9f61aa92009-12-12 05:05:38 +0000212 llvm_unreachable("Unknown typespec!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000213}
214
John McCall32d335e2009-08-03 18:47:27 +0000215const char *DeclSpec::getSpecifierName(TSC C) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000216 switch (C) {
John McCall32d335e2009-08-03 18:47:27 +0000217 case TSC_unspecified: return "unspecified";
218 case TSC_imaginary: return "imaginary";
219 case TSC_complex: return "complex";
Reid Spencer5f016e22007-07-11 17:01:13 +0000220 }
Jeffrey Yasskin9f61aa92009-12-12 05:05:38 +0000221 llvm_unreachable("Unknown typespec!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000222}
223
224
John McCall32d335e2009-08-03 18:47:27 +0000225const char *DeclSpec::getSpecifierName(TSS S) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000226 switch (S) {
John McCall32d335e2009-08-03 18:47:27 +0000227 case TSS_unspecified: return "unspecified";
228 case TSS_signed: return "signed";
229 case TSS_unsigned: return "unsigned";
Reid Spencer5f016e22007-07-11 17:01:13 +0000230 }
Jeffrey Yasskin9f61aa92009-12-12 05:05:38 +0000231 llvm_unreachable("Unknown typespec!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000232}
233
234const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
235 switch (T) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000236 case DeclSpec::TST_unspecified: return "unspecified";
237 case DeclSpec::TST_void: return "void";
238 case DeclSpec::TST_char: return "char";
Argyrios Kyrtzidis64c438a2008-08-09 16:51:54 +0000239 case DeclSpec::TST_wchar: return "wchar_t";
Alisdair Meredithf5c209d2009-07-14 06:30:34 +0000240 case DeclSpec::TST_char16: return "char16_t";
241 case DeclSpec::TST_char32: return "char32_t";
Reid Spencer5f016e22007-07-11 17:01:13 +0000242 case DeclSpec::TST_int: return "int";
243 case DeclSpec::TST_float: return "float";
244 case DeclSpec::TST_double: return "double";
245 case DeclSpec::TST_bool: return "_Bool";
246 case DeclSpec::TST_decimal32: return "_Decimal32";
247 case DeclSpec::TST_decimal64: return "_Decimal64";
248 case DeclSpec::TST_decimal128: return "_Decimal128";
249 case DeclSpec::TST_enum: return "enum";
Chris Lattner99dc9142008-04-13 18:59:07 +0000250 case DeclSpec::TST_class: return "class";
Reid Spencer5f016e22007-07-11 17:01:13 +0000251 case DeclSpec::TST_union: return "union";
252 case DeclSpec::TST_struct: return "struct";
Douglas Gregor1a51b4a2009-02-09 15:09:02 +0000253 case DeclSpec::TST_typename: return "type-name";
Steve Naroffd1861fd2007-07-31 12:34:36 +0000254 case DeclSpec::TST_typeofType:
255 case DeclSpec::TST_typeofExpr: return "typeof";
John McCall32d335e2009-08-03 18:47:27 +0000256 case DeclSpec::TST_auto: return "auto";
257 case DeclSpec::TST_decltype: return "(decltype)";
258 case DeclSpec::TST_error: return "(error)";
Reid Spencer5f016e22007-07-11 17:01:13 +0000259 }
Jeffrey Yasskin9f61aa92009-12-12 05:05:38 +0000260 llvm_unreachable("Unknown typespec!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000261}
262
John McCall32d335e2009-08-03 18:47:27 +0000263const char *DeclSpec::getSpecifierName(TQ T) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000264 switch (T) {
John McCall32d335e2009-08-03 18:47:27 +0000265 case DeclSpec::TQ_unspecified: return "unspecified";
266 case DeclSpec::TQ_const: return "const";
267 case DeclSpec::TQ_restrict: return "restrict";
268 case DeclSpec::TQ_volatile: return "volatile";
Reid Spencer5f016e22007-07-11 17:01:13 +0000269 }
Jeffrey Yasskin9f61aa92009-12-12 05:05:38 +0000270 llvm_unreachable("Unknown typespec!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000271}
272
273bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
John McCallfec54012009-08-03 20:12:06 +0000274 const char *&PrevSpec,
Peter Collingbournee2f82f72011-02-11 19:59:54 +0000275 unsigned &DiagID,
276 const LangOptions &Lang) {
277 // OpenCL prohibits extern, auto, register, and static
278 // It seems sensible to prohibit private_extern too
279 if (Lang.OpenCL) {
280 switch (S) {
281 case SCS_extern:
282 case SCS_private_extern:
283 case SCS_auto:
284 case SCS_register:
285 case SCS_static:
286 DiagID = diag::err_not_opencl_storage_class_specifier;
287 PrevSpec = getSpecifierName(S);
288 return true;
289 default:
290 break;
291 }
292 }
293
Abramo Bagnara35f9a192010-07-30 16:47:02 +0000294 if (StorageClassSpec != SCS_unspecified) {
295 // Changing storage class is allowed only if the previous one
296 // was the 'extern' that is part of a linkage specification and
297 // the new storage class is 'typedef'.
298 if (!(SCS_extern_in_linkage_spec &&
299 StorageClassSpec == SCS_extern &&
300 S == SCS_typedef))
301 return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID);
302 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000303 StorageClassSpec = S;
304 StorageClassSpecLoc = Loc;
Sebastian Redl669d5d72008-11-14 23:42:31 +0000305 assert((unsigned)S == StorageClassSpec && "SCS constants overflow bitfield");
Reid Spencer5f016e22007-07-11 17:01:13 +0000306 return false;
307}
308
Mike Stump1eb44332009-09-09 15:08:12 +0000309bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc,
John McCallfec54012009-08-03 20:12:06 +0000310 const char *&PrevSpec,
311 unsigned &DiagID) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000312 if (SCS_thread_specified) {
313 PrevSpec = "__thread";
John McCallfec54012009-08-03 20:12:06 +0000314 DiagID = diag::ext_duplicate_declspec;
Reid Spencer5f016e22007-07-11 17:01:13 +0000315 return true;
316 }
317 SCS_thread_specified = true;
318 SCS_threadLoc = Loc;
319 return false;
320}
321
Reid Spencer5f016e22007-07-11 17:01:13 +0000322/// These methods set the specified attribute of the DeclSpec, but return true
323/// and ignore the request if invalid (e.g. "extern" then "auto" is
324/// specified).
325bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
John McCallfec54012009-08-03 20:12:06 +0000326 const char *&PrevSpec,
327 unsigned &DiagID) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000328 if (TypeSpecWidth != TSW_unspecified &&
329 // Allow turning long -> long long.
330 (W != TSW_longlong || TypeSpecWidth != TSW_long))
John McCallfec54012009-08-03 20:12:06 +0000331 return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
Reid Spencer5f016e22007-07-11 17:01:13 +0000332 TypeSpecWidth = W;
333 TSWLoc = Loc;
Chris Lattner788b0fd2010-06-23 06:00:24 +0000334 if (TypeAltiVecVector && !TypeAltiVecBool &&
335 ((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) {
John Thompson82287d12010-02-05 00:12:22 +0000336 PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
337 DiagID = diag::warn_vector_long_decl_spec_combination;
338 return true;
339 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000340 return false;
341}
342
Mike Stump1eb44332009-09-09 15:08:12 +0000343bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc,
John McCallfec54012009-08-03 20:12:06 +0000344 const char *&PrevSpec,
345 unsigned &DiagID) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000346 if (TypeSpecComplex != TSC_unspecified)
John McCallfec54012009-08-03 20:12:06 +0000347 return BadSpecifier(C, (TSC)TypeSpecComplex, PrevSpec, DiagID);
Reid Spencer5f016e22007-07-11 17:01:13 +0000348 TypeSpecComplex = C;
349 TSCLoc = Loc;
350 return false;
351}
352
Mike Stump1eb44332009-09-09 15:08:12 +0000353bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc,
John McCallfec54012009-08-03 20:12:06 +0000354 const char *&PrevSpec,
355 unsigned &DiagID) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000356 if (TypeSpecSign != TSS_unspecified)
John McCallfec54012009-08-03 20:12:06 +0000357 return BadSpecifier(S, (TSS)TypeSpecSign, PrevSpec, DiagID);
Reid Spencer5f016e22007-07-11 17:01:13 +0000358 TypeSpecSign = S;
359 TSSLoc = Loc;
360 return false;
361}
362
363bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
John McCallfec54012009-08-03 20:12:06 +0000364 const char *&PrevSpec,
365 unsigned &DiagID,
John McCallb3d87482010-08-24 05:47:05 +0000366 ParsedType Rep) {
367 assert(isTypeRep(T) && "T does not store a type");
368 assert(Rep && "no type provided!");
369 if (TypeSpecType != TST_unspecified) {
370 PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
371 DiagID = diag::err_invalid_decl_spec_combination;
372 return true;
373 }
374 TypeSpecType = T;
375 TypeRep = Rep;
376 TSTLoc = Loc;
377 TypeSpecOwned = false;
378 return false;
379}
380
381bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
382 const char *&PrevSpec,
383 unsigned &DiagID,
384 Expr *Rep) {
385 assert(isExprRep(T) && "T does not store an expr");
386 assert(Rep && "no expression provided!");
387 if (TypeSpecType != TST_unspecified) {
388 PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
389 DiagID = diag::err_invalid_decl_spec_combination;
390 return true;
391 }
392 TypeSpecType = T;
393 ExprRep = Rep;
394 TSTLoc = Loc;
395 TypeSpecOwned = false;
396 return false;
397}
398
399bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
400 const char *&PrevSpec,
401 unsigned &DiagID,
402 Decl *Rep, bool Owned) {
403 assert(isDeclRep(T) && "T does not store a decl");
404 // Unlike the other cases, we don't assert that we actually get a decl.
405
406 if (TypeSpecType != TST_unspecified) {
407 PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
408 DiagID = diag::err_invalid_decl_spec_combination;
409 return true;
410 }
411 TypeSpecType = T;
412 DeclRep = Rep;
413 TSTLoc = Loc;
414 TypeSpecOwned = Owned;
415 return false;
416}
417
418bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
419 const char *&PrevSpec,
420 unsigned &DiagID) {
421 assert(!isDeclRep(T) && !isTypeRep(T) && !isExprRep(T) &&
422 "rep required for these type-spec kinds!");
John McCallfec54012009-08-03 20:12:06 +0000423 if (TypeSpecType != TST_unspecified) {
424 PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
425 DiagID = diag::err_invalid_decl_spec_combination;
426 return true;
427 }
Chris Lattner788b0fd2010-06-23 06:00:24 +0000428 if (TypeAltiVecVector && (T == TST_bool) && !TypeAltiVecBool) {
429 TypeAltiVecBool = true;
430 TSTLoc = Loc;
431 return false;
432 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000433 TypeSpecType = T;
Reid Spencer5f016e22007-07-11 17:01:13 +0000434 TSTLoc = Loc;
John McCallb3d87482010-08-24 05:47:05 +0000435 TypeSpecOwned = false;
Chris Lattner788b0fd2010-06-23 06:00:24 +0000436 if (TypeAltiVecVector && !TypeAltiVecBool && (TypeSpecType == TST_double)) {
John Thompson82287d12010-02-05 00:12:22 +0000437 PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
Chris Lattner788b0fd2010-06-23 06:00:24 +0000438 DiagID = diag::err_invalid_vector_decl_spec;
John Thompson82287d12010-02-05 00:12:22 +0000439 return true;
440 }
441 return false;
442}
443
444bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
445 const char *&PrevSpec, unsigned &DiagID) {
446 if (TypeSpecType != TST_unspecified) {
447 PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
448 DiagID = diag::err_invalid_vector_decl_spec_combination;
449 return true;
450 }
451 TypeAltiVecVector = isAltiVecVector;
452 AltiVecLoc = Loc;
453 return false;
454}
455
456bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
457 const char *&PrevSpec, unsigned &DiagID) {
Chris Lattner788b0fd2010-06-23 06:00:24 +0000458 if (!TypeAltiVecVector || TypeAltiVecPixel ||
459 (TypeSpecType != TST_unspecified)) {
John Thompson82287d12010-02-05 00:12:22 +0000460 PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
461 DiagID = diag::err_invalid_pixel_decl_spec_combination;
462 return true;
463 }
John Thompson82287d12010-02-05 00:12:22 +0000464 TypeAltiVecPixel = isAltiVecPixel;
465 TSTLoc = Loc;
Reid Spencer5f016e22007-07-11 17:01:13 +0000466 return false;
467}
468
Douglas Gregorddc29e12009-02-06 22:42:48 +0000469bool DeclSpec::SetTypeSpecError() {
470 TypeSpecType = TST_error;
John McCall9e46b8c2010-08-26 17:22:34 +0000471 TypeSpecOwned = false;
Douglas Gregorddc29e12009-02-06 22:42:48 +0000472 TSTLoc = SourceLocation();
473 return false;
474}
475
Reid Spencer5f016e22007-07-11 17:01:13 +0000476bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
John McCallfec54012009-08-03 20:12:06 +0000477 unsigned &DiagID, const LangOptions &Lang) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000478 // Duplicates turn into warnings pre-C99.
479 if ((TypeQualifiers & T) && !Lang.C99)
John McCallfec54012009-08-03 20:12:06 +0000480 return BadSpecifier(T, T, PrevSpec, DiagID);
Reid Spencer5f016e22007-07-11 17:01:13 +0000481 TypeQualifiers |= T;
Mike Stump1eb44332009-09-09 15:08:12 +0000482
Reid Spencer5f016e22007-07-11 17:01:13 +0000483 switch (T) {
484 default: assert(0 && "Unknown type qualifier!");
485 case TQ_const: TQ_constLoc = Loc; break;
486 case TQ_restrict: TQ_restrictLoc = Loc; break;
487 case TQ_volatile: TQ_volatileLoc = Loc; break;
488 }
489 return false;
490}
491
John McCallfec54012009-08-03 20:12:06 +0000492bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
493 unsigned &DiagID) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000494 // 'inline inline' is ok.
495 FS_inline_specified = true;
496 FS_inlineLoc = Loc;
497 return false;
498}
499
John McCallfec54012009-08-03 20:12:06 +0000500bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec,
501 unsigned &DiagID) {
Douglas Gregorb48fe382008-10-31 09:07:45 +0000502 // 'virtual virtual' is ok.
503 FS_virtual_specified = true;
504 FS_virtualLoc = Loc;
505 return false;
506}
507
John McCallfec54012009-08-03 20:12:06 +0000508bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec,
509 unsigned &DiagID) {
Douglas Gregorb48fe382008-10-31 09:07:45 +0000510 // 'explicit explicit' is ok.
511 FS_explicit_specified = true;
512 FS_explicitLoc = Loc;
513 return false;
514}
515
John McCallfec54012009-08-03 20:12:06 +0000516bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
517 unsigned &DiagID) {
Anders Carlssonf47f7a12009-05-06 04:46:28 +0000518 if (Friend_specified) {
519 PrevSpec = "friend";
John McCallfec54012009-08-03 20:12:06 +0000520 DiagID = diag::ext_duplicate_declspec;
Anders Carlssonf47f7a12009-05-06 04:46:28 +0000521 return true;
522 }
John McCallfec54012009-08-03 20:12:06 +0000523
Anders Carlssonf47f7a12009-05-06 04:46:28 +0000524 Friend_specified = true;
525 FriendLoc = Loc;
526 return false;
527}
Reid Spencer5f016e22007-07-11 17:01:13 +0000528
Sebastian Redl2ac67232009-11-05 15:47:02 +0000529bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
530 unsigned &DiagID) {
531 // 'constexpr constexpr' is ok.
532 Constexpr_specified = true;
533 ConstexprLoc = Loc;
534 return false;
535}
536
John McCalld226f652010-08-21 09:40:31 +0000537void DeclSpec::setProtocolQualifiers(Decl * const *Protos,
Argyrios Kyrtzidise3a535b2009-09-29 19:42:11 +0000538 unsigned NP,
539 SourceLocation *ProtoLocs,
540 SourceLocation LAngleLoc) {
541 if (NP == 0) return;
John McCalld226f652010-08-21 09:40:31 +0000542 ProtocolQualifiers = new Decl*[NP];
Argyrios Kyrtzidise3a535b2009-09-29 19:42:11 +0000543 ProtocolLocs = new SourceLocation[NP];
John McCalld226f652010-08-21 09:40:31 +0000544 memcpy((void*)ProtocolQualifiers, Protos, sizeof(Decl*)*NP);
Argyrios Kyrtzidise3a535b2009-09-29 19:42:11 +0000545 memcpy(ProtocolLocs, ProtoLocs, sizeof(SourceLocation)*NP);
546 NumProtocolQualifiers = NP;
547 ProtocolLAngleLoc = LAngleLoc;
548}
549
Douglas Gregorddf889a2010-01-18 18:04:31 +0000550void DeclSpec::SaveWrittenBuiltinSpecs() {
551 writtenBS.Sign = getTypeSpecSign();
552 writtenBS.Width = getTypeSpecWidth();
553 writtenBS.Type = getTypeSpecType();
554 // Search the list of attributes for the presence of a mode attribute.
555 writtenBS.ModeAttr = false;
John McCall7f040a92010-12-24 02:08:15 +0000556 AttributeList* attrs = getAttributes().getList();
Douglas Gregorddf889a2010-01-18 18:04:31 +0000557 while (attrs) {
558 if (attrs->getKind() == AttributeList::AT_mode) {
559 writtenBS.ModeAttr = true;
560 break;
561 }
562 attrs = attrs->getNext();
563 }
564}
565
Abramo Bagnara35f9a192010-07-30 16:47:02 +0000566void DeclSpec::SaveStorageSpecifierAsWritten() {
567 if (SCS_extern_in_linkage_spec && StorageClassSpec == SCS_extern)
568 // If 'extern' is part of a linkage specification,
569 // then it is not a storage class "as written".
570 StorageClassSpecAsWritten = SCS_unspecified;
571 else
572 StorageClassSpecAsWritten = StorageClassSpec;
573}
574
Reid Spencer5f016e22007-07-11 17:01:13 +0000575/// Finish - This does final analysis of the declspec, rejecting things like
576/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
577/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
578/// DeclSpec is guaranteed self-consistent, even if an error occurred.
Douglas Gregor9b3064b2009-04-01 22:41:11 +0000579void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
Douglas Gregorddf889a2010-01-18 18:04:31 +0000580 // Before possibly changing their values, save specs as written.
581 SaveWrittenBuiltinSpecs();
Douglas Gregor16573fa2010-04-19 22:54:31 +0000582 SaveStorageSpecifierAsWritten();
Douglas Gregorddf889a2010-01-18 18:04:31 +0000583
Reid Spencer5f016e22007-07-11 17:01:13 +0000584 // Check the type specifier components first.
585
Chris Lattner788b0fd2010-06-23 06:00:24 +0000586 // Validate and finalize AltiVec vector declspec.
587 if (TypeAltiVecVector) {
588 if (TypeAltiVecBool) {
589 // Sign specifiers are not allowed with vector bool. (PIM 2.1)
590 if (TypeSpecSign != TSS_unspecified) {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000591 Diag(D, TSSLoc, diag::err_invalid_vector_bool_decl_spec)
Chris Lattner788b0fd2010-06-23 06:00:24 +0000592 << getSpecifierName((TSS)TypeSpecSign);
593 }
594
595 // Only char/int are valid with vector bool. (PIM 2.1)
Duncan Sands2e964a922010-06-23 19:34:52 +0000596 if (((TypeSpecType != TST_unspecified) && (TypeSpecType != TST_char) &&
597 (TypeSpecType != TST_int)) || TypeAltiVecPixel) {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000598 Diag(D, TSTLoc, diag::err_invalid_vector_bool_decl_spec)
Chris Lattner788b0fd2010-06-23 06:00:24 +0000599 << (TypeAltiVecPixel ? "__pixel" :
600 getSpecifierName((TST)TypeSpecType));
601 }
602
603 // Only 'short' is valid with vector bool. (PIM 2.1)
604 if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short))
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000605 Diag(D, TSWLoc, diag::err_invalid_vector_bool_decl_spec)
Chris Lattner788b0fd2010-06-23 06:00:24 +0000606 << getSpecifierName((TSW)TypeSpecWidth);
607
608 // Elements of vector bool are interpreted as unsigned. (PIM 2.1)
609 if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) ||
610 (TypeSpecWidth != TSW_unspecified))
611 TypeSpecSign = TSS_unsigned;
612 }
613
614 if (TypeAltiVecPixel) {
615 //TODO: perform validation
616 TypeSpecType = TST_int;
617 TypeSpecSign = TSS_unsigned;
618 TypeSpecWidth = TSW_short;
John McCall9e46b8c2010-08-26 17:22:34 +0000619 TypeSpecOwned = false;
Chris Lattner788b0fd2010-06-23 06:00:24 +0000620 }
621 }
622
Argyrios Kyrtzidis64c438a2008-08-09 16:51:54 +0000623 // signed/unsigned are only valid with int/char/wchar_t.
Reid Spencer5f016e22007-07-11 17:01:13 +0000624 if (TypeSpecSign != TSS_unspecified) {
625 if (TypeSpecType == TST_unspecified)
626 TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
Argyrios Kyrtzidis64c438a2008-08-09 16:51:54 +0000627 else if (TypeSpecType != TST_int &&
628 TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000629 Diag(D, TSSLoc, diag::err_invalid_sign_spec)
Chris Lattner254be6a2008-11-22 08:32:36 +0000630 << getSpecifierName((TST)TypeSpecType);
Reid Spencer5f016e22007-07-11 17:01:13 +0000631 // signed double -> double.
632 TypeSpecSign = TSS_unspecified;
633 }
634 }
635
636 // Validate the width of the type.
637 switch (TypeSpecWidth) {
638 case TSW_unspecified: break;
639 case TSW_short: // short int
640 case TSW_longlong: // long long int
641 if (TypeSpecType == TST_unspecified)
642 TypeSpecType = TST_int; // short -> short int, long long -> long long int.
643 else if (TypeSpecType != TST_int) {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000644 Diag(D, TSWLoc,
Reid Spencer5f016e22007-07-11 17:01:13 +0000645 TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec
Chris Lattner254be6a2008-11-22 08:32:36 +0000646 : diag::err_invalid_longlong_spec)
647 << getSpecifierName((TST)TypeSpecType);
Reid Spencer5f016e22007-07-11 17:01:13 +0000648 TypeSpecType = TST_int;
John McCall9e46b8c2010-08-26 17:22:34 +0000649 TypeSpecOwned = false;
Reid Spencer5f016e22007-07-11 17:01:13 +0000650 }
651 break;
652 case TSW_long: // long double, long int
653 if (TypeSpecType == TST_unspecified)
654 TypeSpecType = TST_int; // long -> long int.
655 else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000656 Diag(D, TSWLoc, diag::err_invalid_long_spec)
Chris Lattner254be6a2008-11-22 08:32:36 +0000657 << getSpecifierName((TST)TypeSpecType);
Reid Spencer5f016e22007-07-11 17:01:13 +0000658 TypeSpecType = TST_int;
John McCall9e46b8c2010-08-26 17:22:34 +0000659 TypeSpecOwned = false;
Reid Spencer5f016e22007-07-11 17:01:13 +0000660 }
661 break;
662 }
Mike Stump1eb44332009-09-09 15:08:12 +0000663
Reid Spencer5f016e22007-07-11 17:01:13 +0000664 // TODO: if the implementation does not implement _Complex or _Imaginary,
665 // disallow their use. Need information about the backend.
666 if (TypeSpecComplex != TSC_unspecified) {
667 if (TypeSpecType == TST_unspecified) {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000668 Diag(D, TSCLoc, diag::ext_plain_complex)
Douglas Gregor849b2432010-03-31 17:46:05 +0000669 << FixItHint::CreateInsertion(
Douglas Gregor9b3064b2009-04-01 22:41:11 +0000670 PP.getLocForEndOfToken(getTypeSpecComplexLoc()),
671 " double");
Reid Spencer5f016e22007-07-11 17:01:13 +0000672 TypeSpecType = TST_double; // _Complex -> _Complex double.
673 } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
674 // Note that this intentionally doesn't include _Complex _Bool.
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000675 Diag(D, TSTLoc, diag::ext_integer_complex);
Reid Spencer5f016e22007-07-11 17:01:13 +0000676 } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000677 Diag(D, TSCLoc, diag::err_invalid_complex_spec)
Chris Lattner254be6a2008-11-22 08:32:36 +0000678 << getSpecifierName((TST)TypeSpecType);
Reid Spencer5f016e22007-07-11 17:01:13 +0000679 TypeSpecComplex = TSC_unspecified;
680 }
681 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000682
John McCall67d1a672009-08-06 02:15:43 +0000683 // C++ [class.friend]p6:
684 // No storage-class-specifier shall appear in the decl-specifier-seq
685 // of a friend declaration.
686 if (isFriendSpecified() && getStorageClassSpec()) {
687 DeclSpec::SCS SC = getStorageClassSpec();
688 const char *SpecName = getSpecifierName(SC);
689
690 SourceLocation SCLoc = getStorageClassSpecLoc();
691 SourceLocation SCEndLoc = SCLoc.getFileLocWithOffset(strlen(SpecName));
692
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000693 Diag(D, SCLoc, diag::err_friend_storage_spec)
John McCall67d1a672009-08-06 02:15:43 +0000694 << SpecName
Douglas Gregor849b2432010-03-31 17:46:05 +0000695 << FixItHint::CreateRemoval(SourceRange(SCLoc, SCEndLoc));
John McCall67d1a672009-08-06 02:15:43 +0000696
697 ClearStorageClassSpecs();
698 }
699
John McCall9e46b8c2010-08-26 17:22:34 +0000700 assert(!TypeSpecOwned || isDeclRep((TST) TypeSpecType));
701
Reid Spencer5f016e22007-07-11 17:01:13 +0000702 // Okay, now we can infer the real type.
Mike Stump1eb44332009-09-09 15:08:12 +0000703
Reid Spencer5f016e22007-07-11 17:01:13 +0000704 // TODO: return "auto function" and other bad things based on the real type.
Mike Stump1eb44332009-09-09 15:08:12 +0000705
Reid Spencer5f016e22007-07-11 17:01:13 +0000706 // 'data definition has no type or storage class'?
707}
Daniel Dunbare4858a62008-08-11 03:45:03 +0000708
Sebastian Redla4ed0d82008-12-28 15:28:59 +0000709bool DeclSpec::isMissingDeclaratorOk() {
710 TST tst = getTypeSpecType();
John McCallb3d87482010-08-24 05:47:05 +0000711 return isDeclRep(tst) && getRepAsDecl() != 0 &&
712 StorageClassSpec != DeclSpec::SCS_typedef;
Sebastian Redla4ed0d82008-12-28 15:28:59 +0000713}
Douglas Gregor3f9a0562009-11-03 01:35:08 +0000714
715void UnqualifiedId::clear() {
716 if (Kind == IK_TemplateId)
717 TemplateId->Destroy();
718
719 Kind = IK_Identifier;
720 Identifier = 0;
721 StartLocation = SourceLocation();
722 EndLocation = SourceLocation();
723}
724
725void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc,
726 OverloadedOperatorKind Op,
727 SourceLocation SymbolLocations[3]) {
728 Kind = IK_OperatorFunctionId;
729 StartLocation = OperatorLoc;
730 EndLocation = OperatorLoc;
731 OperatorFunctionId.Operator = Op;
732 for (unsigned I = 0; I != 3; ++I) {
733 OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding();
734
735 if (SymbolLocations[I].isValid())
736 EndLocation = SymbolLocations[I];
737 }
738}
Anders Carlssonb971dbd2011-01-17 03:05:47 +0000739
Anders Carlssoncc54d592011-01-22 16:56:46 +0000740bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc,
Anders Carlsson46127a92011-01-22 15:58:16 +0000741 const char *&PrevSpec) {
Anders Carlssonb971dbd2011-01-17 03:05:47 +0000742 if (Specifiers & VS) {
743 PrevSpec = getSpecifierName(VS);
744 return true;
745 }
746
747 Specifiers |= VS;
748
749 switch (VS) {
750 default: assert(0 && "Unknown specifier!");
751 case VS_Override: VS_overrideLoc = Loc; break;
752 case VS_Final: VS_finalLoc = Loc; break;
753 case VS_New: VS_newLoc = Loc; break;
754 }
Anders Carlsson46127a92011-01-22 15:58:16 +0000755
Anders Carlssonb971dbd2011-01-17 03:05:47 +0000756 return false;
757}
758
Anders Carlssoncc54d592011-01-22 16:56:46 +0000759const char *VirtSpecifiers::getSpecifierName(Specifier VS) {
Anders Carlssonc46bb7d2011-01-22 15:11:37 +0000760 switch (VS) {
761 default: assert(0 && "Unknown specifier");
762 case VS_Override: return "override";
763 case VS_Final: return "final";
764 case VS_New: return "new";
765 }
766}
Anders Carlsson46127a92011-01-22 15:58:16 +0000767
Anders Carlssoncc54d592011-01-22 16:56:46 +0000768bool ClassVirtSpecifiers::SetSpecifier(Specifier CVS, SourceLocation Loc,
Anders Carlsson46127a92011-01-22 15:58:16 +0000769 const char *&PrevSpec) {
770 if (Specifiers & CVS) {
771 PrevSpec = getSpecifierName(CVS);
772 return true;
773 }
774
775 Specifiers |= CVS;
776
777 switch (CVS) {
778 default: assert(0 && "Unknown specifier!");
779 case CVS_Final: CVS_finalLoc = Loc; break;
780 case CVS_Explicit: CVS_explicitLoc = Loc; break;
781 }
782
783 return false;
784}
785
Anders Carlssoncc54d592011-01-22 16:56:46 +0000786const char *ClassVirtSpecifiers::getSpecifierName(Specifier CVS) {
Anders Carlsson46127a92011-01-22 15:58:16 +0000787 switch (CVS) {
788 default: assert(0 && "Unknown specifier");
789 case CVS_Final: return "final";
790 case CVS_Explicit: return "explicit";
791 }
792}
793