/src/llvm-project/clang/lib/Sema/DeclSpec.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- DeclSpec.cpp - Declaration Specifier Semantic Analysis -----------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file implements semantic analysis for declaration specifiers. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "clang/Sema/DeclSpec.h" |
14 | | #include "clang/AST/ASTContext.h" |
15 | | #include "clang/AST/DeclCXX.h" |
16 | | #include "clang/AST/Expr.h" |
17 | | #include "clang/AST/LocInfoType.h" |
18 | | #include "clang/AST/TypeLoc.h" |
19 | | #include "clang/Basic/LangOptions.h" |
20 | | #include "clang/Basic/SourceManager.h" |
21 | | #include "clang/Basic/Specifiers.h" |
22 | | #include "clang/Basic/TargetInfo.h" |
23 | | #include "clang/Sema/ParsedTemplate.h" |
24 | | #include "clang/Sema/Sema.h" |
25 | | #include "clang/Sema/SemaDiagnostic.h" |
26 | | #include "llvm/ADT/STLExtras.h" |
27 | | #include "llvm/ADT/SmallString.h" |
28 | | #include <cstring> |
29 | | using namespace clang; |
30 | | |
31 | | |
32 | 0 | void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) { |
33 | 0 | assert(TemplateId && "NULL template-id annotation?"); |
34 | 0 | assert(!TemplateId->isInvalid() && |
35 | 0 | "should not convert invalid template-ids to unqualified-ids"); |
36 | | |
37 | 0 | Kind = UnqualifiedIdKind::IK_TemplateId; |
38 | 0 | this->TemplateId = TemplateId; |
39 | 0 | StartLocation = TemplateId->TemplateNameLoc; |
40 | 0 | EndLocation = TemplateId->RAngleLoc; |
41 | 0 | } |
42 | | |
43 | 0 | void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) { |
44 | 0 | assert(TemplateId && "NULL template-id annotation?"); |
45 | 0 | assert(!TemplateId->isInvalid() && |
46 | 0 | "should not convert invalid template-ids to unqualified-ids"); |
47 | | |
48 | 0 | Kind = UnqualifiedIdKind::IK_ConstructorTemplateId; |
49 | 0 | this->TemplateId = TemplateId; |
50 | 0 | StartLocation = TemplateId->TemplateNameLoc; |
51 | 0 | EndLocation = TemplateId->RAngleLoc; |
52 | 0 | } |
53 | | |
54 | | void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc, |
55 | 0 | TypeLoc TL, SourceLocation ColonColonLoc) { |
56 | 0 | Builder.Extend(Context, TemplateKWLoc, TL, ColonColonLoc); |
57 | 0 | if (Range.getBegin().isInvalid()) |
58 | 0 | Range.setBegin(TL.getBeginLoc()); |
59 | 0 | Range.setEnd(ColonColonLoc); |
60 | |
|
61 | 0 | assert(Range == Builder.getSourceRange() && |
62 | 0 | "NestedNameSpecifierLoc range computation incorrect"); |
63 | 0 | } |
64 | | |
65 | | void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier, |
66 | | SourceLocation IdentifierLoc, |
67 | 0 | SourceLocation ColonColonLoc) { |
68 | 0 | Builder.Extend(Context, Identifier, IdentifierLoc, ColonColonLoc); |
69 | |
|
70 | 0 | if (Range.getBegin().isInvalid()) |
71 | 0 | Range.setBegin(IdentifierLoc); |
72 | 0 | Range.setEnd(ColonColonLoc); |
73 | |
|
74 | 0 | assert(Range == Builder.getSourceRange() && |
75 | 0 | "NestedNameSpecifierLoc range computation incorrect"); |
76 | 0 | } |
77 | | |
78 | | void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace, |
79 | | SourceLocation NamespaceLoc, |
80 | 0 | SourceLocation ColonColonLoc) { |
81 | 0 | Builder.Extend(Context, Namespace, NamespaceLoc, ColonColonLoc); |
82 | |
|
83 | 0 | if (Range.getBegin().isInvalid()) |
84 | 0 | Range.setBegin(NamespaceLoc); |
85 | 0 | Range.setEnd(ColonColonLoc); |
86 | |
|
87 | 0 | assert(Range == Builder.getSourceRange() && |
88 | 0 | "NestedNameSpecifierLoc range computation incorrect"); |
89 | 0 | } |
90 | | |
91 | | void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias, |
92 | | SourceLocation AliasLoc, |
93 | 0 | SourceLocation ColonColonLoc) { |
94 | 0 | Builder.Extend(Context, Alias, AliasLoc, ColonColonLoc); |
95 | |
|
96 | 0 | if (Range.getBegin().isInvalid()) |
97 | 0 | Range.setBegin(AliasLoc); |
98 | 0 | Range.setEnd(ColonColonLoc); |
99 | |
|
100 | 0 | assert(Range == Builder.getSourceRange() && |
101 | 0 | "NestedNameSpecifierLoc range computation incorrect"); |
102 | 0 | } |
103 | | |
104 | | void CXXScopeSpec::MakeGlobal(ASTContext &Context, |
105 | 0 | SourceLocation ColonColonLoc) { |
106 | 0 | Builder.MakeGlobal(Context, ColonColonLoc); |
107 | |
|
108 | 0 | Range = SourceRange(ColonColonLoc); |
109 | |
|
110 | 0 | assert(Range == Builder.getSourceRange() && |
111 | 0 | "NestedNameSpecifierLoc range computation incorrect"); |
112 | 0 | } |
113 | | |
114 | | void CXXScopeSpec::MakeSuper(ASTContext &Context, CXXRecordDecl *RD, |
115 | | SourceLocation SuperLoc, |
116 | 0 | SourceLocation ColonColonLoc) { |
117 | 0 | Builder.MakeSuper(Context, RD, SuperLoc, ColonColonLoc); |
118 | |
|
119 | 0 | Range.setBegin(SuperLoc); |
120 | 0 | Range.setEnd(ColonColonLoc); |
121 | |
|
122 | 0 | assert(Range == Builder.getSourceRange() && |
123 | 0 | "NestedNameSpecifierLoc range computation incorrect"); |
124 | 0 | } |
125 | | |
126 | | void CXXScopeSpec::MakeTrivial(ASTContext &Context, |
127 | 0 | NestedNameSpecifier *Qualifier, SourceRange R) { |
128 | 0 | Builder.MakeTrivial(Context, Qualifier, R); |
129 | 0 | Range = R; |
130 | 0 | } |
131 | | |
132 | 0 | void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) { |
133 | 0 | if (!Other) { |
134 | 0 | Range = SourceRange(); |
135 | 0 | Builder.Clear(); |
136 | 0 | return; |
137 | 0 | } |
138 | | |
139 | 0 | Range = Other.getSourceRange(); |
140 | 0 | Builder.Adopt(Other); |
141 | 0 | assert(Range == Builder.getSourceRange() && |
142 | 0 | "NestedNameSpecifierLoc range computation incorrect"); |
143 | 0 | } |
144 | | |
145 | 0 | SourceLocation CXXScopeSpec::getLastQualifierNameLoc() const { |
146 | 0 | if (!Builder.getRepresentation()) |
147 | 0 | return SourceLocation(); |
148 | 0 | return Builder.getTemporary().getLocalBeginLoc(); |
149 | 0 | } |
150 | | |
151 | | NestedNameSpecifierLoc |
152 | 62 | CXXScopeSpec::getWithLocInContext(ASTContext &Context) const { |
153 | 62 | if (!Builder.getRepresentation()) |
154 | 62 | return NestedNameSpecifierLoc(); |
155 | | |
156 | 0 | return Builder.getWithLocInContext(Context); |
157 | 62 | } |
158 | | |
159 | | /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. |
160 | | /// "TheDeclarator" is the declarator that this will be added to. |
161 | | DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, |
162 | | bool isAmbiguous, |
163 | | SourceLocation LParenLoc, |
164 | | ParamInfo *Params, |
165 | | unsigned NumParams, |
166 | | SourceLocation EllipsisLoc, |
167 | | SourceLocation RParenLoc, |
168 | | bool RefQualifierIsLvalueRef, |
169 | | SourceLocation RefQualifierLoc, |
170 | | SourceLocation MutableLoc, |
171 | | ExceptionSpecificationType |
172 | | ESpecType, |
173 | | SourceRange ESpecRange, |
174 | | ParsedType *Exceptions, |
175 | | SourceRange *ExceptionRanges, |
176 | | unsigned NumExceptions, |
177 | | Expr *NoexceptExpr, |
178 | | CachedTokens *ExceptionSpecTokens, |
179 | | ArrayRef<NamedDecl*> |
180 | | DeclsInPrototype, |
181 | | SourceLocation LocalRangeBegin, |
182 | | SourceLocation LocalRangeEnd, |
183 | | Declarator &TheDeclarator, |
184 | | TypeResult TrailingReturnType, |
185 | | SourceLocation |
186 | | TrailingReturnTypeLoc, |
187 | 84 | DeclSpec *MethodQualifiers) { |
188 | 84 | assert(!(MethodQualifiers && MethodQualifiers->getTypeQualifiers() & DeclSpec::TQ_atomic) && |
189 | 84 | "function cannot have _Atomic qualifier"); |
190 | | |
191 | 0 | DeclaratorChunk I; |
192 | 84 | I.Kind = Function; |
193 | 84 | I.Loc = LocalRangeBegin; |
194 | 84 | I.EndLoc = LocalRangeEnd; |
195 | 84 | new (&I.Fun) FunctionTypeInfo; |
196 | 84 | I.Fun.hasPrototype = hasProto; |
197 | 84 | I.Fun.isVariadic = EllipsisLoc.isValid(); |
198 | 84 | I.Fun.isAmbiguous = isAmbiguous; |
199 | 84 | I.Fun.LParenLoc = LParenLoc; |
200 | 84 | I.Fun.EllipsisLoc = EllipsisLoc; |
201 | 84 | I.Fun.RParenLoc = RParenLoc; |
202 | 84 | I.Fun.DeleteParams = false; |
203 | 84 | I.Fun.NumParams = NumParams; |
204 | 84 | I.Fun.Params = nullptr; |
205 | 84 | I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef; |
206 | 84 | I.Fun.RefQualifierLoc = RefQualifierLoc; |
207 | 84 | I.Fun.MutableLoc = MutableLoc; |
208 | 84 | I.Fun.ExceptionSpecType = ESpecType; |
209 | 84 | I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin(); |
210 | 84 | I.Fun.ExceptionSpecLocEnd = ESpecRange.getEnd(); |
211 | 84 | I.Fun.NumExceptionsOrDecls = 0; |
212 | 84 | I.Fun.Exceptions = nullptr; |
213 | 84 | I.Fun.NoexceptExpr = nullptr; |
214 | 84 | I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() || |
215 | 84 | TrailingReturnType.isInvalid(); |
216 | 84 | I.Fun.TrailingReturnType = TrailingReturnType.get(); |
217 | 84 | I.Fun.TrailingReturnTypeLoc = TrailingReturnTypeLoc; |
218 | 84 | I.Fun.MethodQualifiers = nullptr; |
219 | 84 | I.Fun.QualAttrFactory = nullptr; |
220 | | |
221 | 84 | if (MethodQualifiers && (MethodQualifiers->getTypeQualifiers() || |
222 | 79 | MethodQualifiers->getAttributes().size())) { |
223 | 0 | auto &attrs = MethodQualifiers->getAttributes(); |
224 | 0 | I.Fun.MethodQualifiers = new DeclSpec(attrs.getPool().getFactory()); |
225 | 0 | MethodQualifiers->forEachCVRUQualifier( |
226 | 0 | [&](DeclSpec::TQ TypeQual, StringRef PrintName, SourceLocation SL) { |
227 | 0 | I.Fun.MethodQualifiers->SetTypeQual(TypeQual, SL); |
228 | 0 | }); |
229 | 0 | I.Fun.MethodQualifiers->getAttributes().takeAllFrom(attrs); |
230 | 0 | I.Fun.MethodQualifiers->getAttributePool().takeAllFrom(attrs.getPool()); |
231 | 0 | } |
232 | | |
233 | 84 | assert(I.Fun.ExceptionSpecType == ESpecType && "bitfield overflow"); |
234 | | |
235 | | // new[] a parameter array if needed. |
236 | 84 | if (NumParams) { |
237 | | // If the 'InlineParams' in Declarator is unused and big enough, put our |
238 | | // parameter list there (in an effort to avoid new/delete traffic). If it |
239 | | // is already used (consider a function returning a function pointer) or too |
240 | | // small (function with too many parameters), go to the heap. |
241 | 40 | if (!TheDeclarator.InlineStorageUsed && |
242 | 40 | NumParams <= std::size(TheDeclarator.InlineParams)) { |
243 | 40 | I.Fun.Params = TheDeclarator.InlineParams; |
244 | 40 | new (I.Fun.Params) ParamInfo[NumParams]; |
245 | 40 | I.Fun.DeleteParams = false; |
246 | 40 | TheDeclarator.InlineStorageUsed = true; |
247 | 40 | } else { |
248 | 0 | I.Fun.Params = new DeclaratorChunk::ParamInfo[NumParams]; |
249 | 0 | I.Fun.DeleteParams = true; |
250 | 0 | } |
251 | 80 | for (unsigned i = 0; i < NumParams; i++) |
252 | 40 | I.Fun.Params[i] = std::move(Params[i]); |
253 | 40 | } |
254 | | |
255 | | // Check what exception specification information we should actually store. |
256 | 84 | switch (ESpecType) { |
257 | 84 | default: break; // By default, save nothing. |
258 | 84 | case EST_Dynamic: |
259 | | // new[] an exception array if needed |
260 | 0 | if (NumExceptions) { |
261 | 0 | I.Fun.NumExceptionsOrDecls = NumExceptions; |
262 | 0 | I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; |
263 | 0 | for (unsigned i = 0; i != NumExceptions; ++i) { |
264 | 0 | I.Fun.Exceptions[i].Ty = Exceptions[i]; |
265 | 0 | I.Fun.Exceptions[i].Range = ExceptionRanges[i]; |
266 | 0 | } |
267 | 0 | } |
268 | 0 | break; |
269 | | |
270 | 0 | case EST_DependentNoexcept: |
271 | 0 | case EST_NoexceptFalse: |
272 | 0 | case EST_NoexceptTrue: |
273 | 0 | I.Fun.NoexceptExpr = NoexceptExpr; |
274 | 0 | break; |
275 | | |
276 | 0 | case EST_Unparsed: |
277 | 0 | I.Fun.ExceptionSpecTokens = ExceptionSpecTokens; |
278 | 0 | break; |
279 | 84 | } |
280 | | |
281 | 84 | if (!DeclsInPrototype.empty()) { |
282 | 0 | assert(ESpecType == EST_None && NumExceptions == 0 && |
283 | 0 | "cannot have exception specifiers and decls in prototype"); |
284 | 0 | I.Fun.NumExceptionsOrDecls = DeclsInPrototype.size(); |
285 | | // Copy the array of decls into stable heap storage. |
286 | 0 | I.Fun.DeclsInPrototype = new NamedDecl *[DeclsInPrototype.size()]; |
287 | 0 | for (size_t J = 0; J < DeclsInPrototype.size(); ++J) |
288 | 0 | I.Fun.DeclsInPrototype[J] = DeclsInPrototype[J]; |
289 | 0 | } |
290 | | |
291 | 0 | return I; |
292 | 84 | } |
293 | | |
294 | | void Declarator::setDecompositionBindings( |
295 | | SourceLocation LSquareLoc, |
296 | | ArrayRef<DecompositionDeclarator::Binding> Bindings, |
297 | 0 | SourceLocation RSquareLoc) { |
298 | 0 | assert(!hasName() && "declarator given multiple names!"); |
299 | | |
300 | 0 | BindingGroup.LSquareLoc = LSquareLoc; |
301 | 0 | BindingGroup.RSquareLoc = RSquareLoc; |
302 | 0 | BindingGroup.NumBindings = Bindings.size(); |
303 | 0 | Range.setEnd(RSquareLoc); |
304 | | |
305 | | // We're now past the identifier. |
306 | 0 | SetIdentifier(nullptr, LSquareLoc); |
307 | 0 | Name.EndLocation = RSquareLoc; |
308 | | |
309 | | // Allocate storage for bindings and stash them away. |
310 | 0 | if (Bindings.size()) { |
311 | 0 | if (!InlineStorageUsed && Bindings.size() <= std::size(InlineBindings)) { |
312 | 0 | BindingGroup.Bindings = InlineBindings; |
313 | 0 | BindingGroup.DeleteBindings = false; |
314 | 0 | InlineStorageUsed = true; |
315 | 0 | } else { |
316 | 0 | BindingGroup.Bindings = |
317 | 0 | new DecompositionDeclarator::Binding[Bindings.size()]; |
318 | 0 | BindingGroup.DeleteBindings = true; |
319 | 0 | } |
320 | 0 | std::uninitialized_copy(Bindings.begin(), Bindings.end(), |
321 | 0 | BindingGroup.Bindings); |
322 | 0 | } |
323 | 0 | } |
324 | | |
325 | 0 | bool Declarator::isDeclarationOfFunction() const { |
326 | 0 | for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) { |
327 | 0 | switch (DeclTypeInfo[i].Kind) { |
328 | 0 | case DeclaratorChunk::Function: |
329 | 0 | return true; |
330 | 0 | case DeclaratorChunk::Paren: |
331 | 0 | continue; |
332 | 0 | case DeclaratorChunk::Pointer: |
333 | 0 | case DeclaratorChunk::Reference: |
334 | 0 | case DeclaratorChunk::Array: |
335 | 0 | case DeclaratorChunk::BlockPointer: |
336 | 0 | case DeclaratorChunk::MemberPointer: |
337 | 0 | case DeclaratorChunk::Pipe: |
338 | 0 | return false; |
339 | 0 | } |
340 | 0 | llvm_unreachable("Invalid type chunk"); |
341 | 0 | } |
342 | | |
343 | 0 | switch (DS.getTypeSpecType()) { |
344 | 0 | case TST_atomic: |
345 | 0 | case TST_auto: |
346 | 0 | case TST_auto_type: |
347 | 0 | case TST_bool: |
348 | 0 | case TST_char: |
349 | 0 | case TST_char8: |
350 | 0 | case TST_char16: |
351 | 0 | case TST_char32: |
352 | 0 | case TST_class: |
353 | 0 | case TST_decimal128: |
354 | 0 | case TST_decimal32: |
355 | 0 | case TST_decimal64: |
356 | 0 | case TST_double: |
357 | 0 | case TST_Accum: |
358 | 0 | case TST_Fract: |
359 | 0 | case TST_Float16: |
360 | 0 | case TST_float128: |
361 | 0 | case TST_ibm128: |
362 | 0 | case TST_enum: |
363 | 0 | case TST_error: |
364 | 0 | case TST_float: |
365 | 0 | case TST_half: |
366 | 0 | case TST_int: |
367 | 0 | case TST_int128: |
368 | 0 | case TST_bitint: |
369 | 0 | case TST_struct: |
370 | 0 | case TST_interface: |
371 | 0 | case TST_union: |
372 | 0 | case TST_unknown_anytype: |
373 | 0 | case TST_unspecified: |
374 | 0 | case TST_void: |
375 | 0 | case TST_wchar: |
376 | 0 | case TST_BFloat16: |
377 | 0 | #define GENERIC_IMAGE_TYPE(ImgType, Id) case TST_##ImgType##_t: |
378 | 0 | #include "clang/Basic/OpenCLImageTypes.def" |
379 | 0 | return false; |
380 | | |
381 | 0 | case TST_decltype_auto: |
382 | | // This must have an initializer, so can't be a function declaration, |
383 | | // even if the initializer has function type. |
384 | 0 | return false; |
385 | | |
386 | 0 | case TST_decltype: |
387 | 0 | case TST_typeof_unqualExpr: |
388 | 0 | case TST_typeofExpr: |
389 | 0 | if (Expr *E = DS.getRepAsExpr()) |
390 | 0 | return E->getType()->isFunctionType(); |
391 | 0 | return false; |
392 | | |
393 | 0 | #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case TST_##Trait: |
394 | 0 | #include "clang/Basic/TransformTypeTraits.def" |
395 | 0 | case TST_typename: |
396 | 0 | case TST_typeof_unqualType: |
397 | 0 | case TST_typeofType: { |
398 | 0 | QualType QT = DS.getRepAsType().get(); |
399 | 0 | if (QT.isNull()) |
400 | 0 | return false; |
401 | | |
402 | 0 | if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) |
403 | 0 | QT = LIT->getType(); |
404 | |
|
405 | 0 | if (QT.isNull()) |
406 | 0 | return false; |
407 | | |
408 | 0 | return QT->isFunctionType(); |
409 | 0 | } |
410 | 0 | } |
411 | | |
412 | 0 | llvm_unreachable("Invalid TypeSpecType!"); |
413 | 0 | } |
414 | | |
415 | 0 | bool Declarator::isStaticMember() { |
416 | 0 | assert(getContext() == DeclaratorContext::Member); |
417 | 0 | return getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static || |
418 | 0 | (getName().getKind() == UnqualifiedIdKind::IK_OperatorFunctionId && |
419 | 0 | CXXMethodDecl::isStaticOverloadedOperator( |
420 | 0 | getName().OperatorFunctionId.Operator)); |
421 | 0 | } |
422 | | |
423 | 0 | bool Declarator::isExplicitObjectMemberFunction() { |
424 | 0 | if (!isFunctionDeclarator()) |
425 | 0 | return false; |
426 | 0 | DeclaratorChunk::FunctionTypeInfo &Fun = getFunctionTypeInfo(); |
427 | 0 | if (Fun.NumParams) { |
428 | 0 | auto *P = dyn_cast_or_null<ParmVarDecl>(Fun.Params[0].Param); |
429 | 0 | if (P && P->isExplicitObjectParameter()) |
430 | 0 | return true; |
431 | 0 | } |
432 | 0 | return false; |
433 | 0 | } |
434 | | |
435 | 0 | bool Declarator::isCtorOrDtor() { |
436 | 0 | return (getName().getKind() == UnqualifiedIdKind::IK_ConstructorName) || |
437 | 0 | (getName().getKind() == UnqualifiedIdKind::IK_DestructorName); |
438 | 0 | } |
439 | | |
440 | | void DeclSpec::forEachCVRUQualifier( |
441 | 0 | llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle) { |
442 | 0 | if (TypeQualifiers & TQ_const) |
443 | 0 | Handle(TQ_const, "const", TQ_constLoc); |
444 | 0 | if (TypeQualifiers & TQ_volatile) |
445 | 0 | Handle(TQ_volatile, "volatile", TQ_volatileLoc); |
446 | 0 | if (TypeQualifiers & TQ_restrict) |
447 | 0 | Handle(TQ_restrict, "restrict", TQ_restrictLoc); |
448 | 0 | if (TypeQualifiers & TQ_unaligned) |
449 | 0 | Handle(TQ_unaligned, "unaligned", TQ_unalignedLoc); |
450 | 0 | } |
451 | | |
452 | | void DeclSpec::forEachQualifier( |
453 | 0 | llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle) { |
454 | 0 | forEachCVRUQualifier(Handle); |
455 | | // FIXME: Add code below to iterate through the attributes and call Handle. |
456 | 0 | } |
457 | | |
458 | 47.7k | bool DeclSpec::hasTagDefinition() const { |
459 | 47.7k | if (!TypeSpecOwned) |
460 | 47.7k | return false; |
461 | 0 | return cast<TagDecl>(getRepAsDecl())->isCompleteDefinition(); |
462 | 47.7k | } |
463 | | |
464 | | /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this |
465 | | /// declaration specifier includes. |
466 | | /// |
467 | 97 | unsigned DeclSpec::getParsedSpecifiers() const { |
468 | 97 | unsigned Res = 0; |
469 | 97 | if (StorageClassSpec != SCS_unspecified || |
470 | 97 | ThreadStorageClassSpec != TSCS_unspecified) |
471 | 0 | Res |= PQ_StorageClassSpecifier; |
472 | | |
473 | 97 | if (TypeQualifiers != TQ_unspecified) |
474 | 0 | Res |= PQ_TypeQualifier; |
475 | | |
476 | 97 | if (hasTypeSpecifier()) |
477 | 54 | Res |= PQ_TypeSpecifier; |
478 | | |
479 | 97 | if (FS_inline_specified || FS_virtual_specified || hasExplicitSpecifier() || |
480 | 97 | FS_noreturn_specified || FS_forceinline_specified) |
481 | 0 | Res |= PQ_FunctionSpecifier; |
482 | 97 | return Res; |
483 | 97 | } |
484 | | |
485 | | template <class T> static bool BadSpecifier(T TNew, T TPrev, |
486 | | const char *&PrevSpec, |
487 | | unsigned &DiagID, |
488 | 0 | bool IsExtension = true) { |
489 | 0 | PrevSpec = DeclSpec::getSpecifierName(TPrev); |
490 | 0 | if (TNew != TPrev) |
491 | 0 | DiagID = diag::err_invalid_decl_spec_combination; |
492 | 0 | else |
493 | 0 | DiagID = IsExtension ? diag::ext_warn_duplicate_declspec : |
494 | 0 | diag::warn_duplicate_declspec; |
495 | 0 | return true; |
496 | 0 | } Unexecuted instantiation: DeclSpec.cpp:bool BadSpecifier<clang::DeclSpec::SCS>(clang::DeclSpec::SCS, clang::DeclSpec::SCS, char const*&, unsigned int&, bool) Unexecuted instantiation: DeclSpec.cpp:bool BadSpecifier<clang::ThreadStorageClassSpecifier>(clang::ThreadStorageClassSpecifier, clang::ThreadStorageClassSpecifier, char const*&, unsigned int&, bool) Unexecuted instantiation: DeclSpec.cpp:bool BadSpecifier<clang::TypeSpecifierWidth>(clang::TypeSpecifierWidth, clang::TypeSpecifierWidth, char const*&, unsigned int&, bool) Unexecuted instantiation: DeclSpec.cpp:bool BadSpecifier<clang::DeclSpec::TSC>(clang::DeclSpec::TSC, clang::DeclSpec::TSC, char const*&, unsigned int&, bool) Unexecuted instantiation: DeclSpec.cpp:bool BadSpecifier<clang::TypeSpecifierSign>(clang::TypeSpecifierSign, clang::TypeSpecifierSign, char const*&, unsigned int&, bool) Unexecuted instantiation: DeclSpec.cpp:bool BadSpecifier<clang::DeclSpec::TQ>(clang::DeclSpec::TQ, clang::DeclSpec::TQ, char const*&, unsigned int&, bool) Unexecuted instantiation: DeclSpec.cpp:bool BadSpecifier<clang::ConstexprSpecKind>(clang::ConstexprSpecKind, clang::ConstexprSpecKind, char const*&, unsigned int&, bool) |
497 | | |
498 | 0 | const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) { |
499 | 0 | switch (S) { |
500 | 0 | case DeclSpec::SCS_unspecified: return "unspecified"; |
501 | 0 | case DeclSpec::SCS_typedef: return "typedef"; |
502 | 0 | case DeclSpec::SCS_extern: return "extern"; |
503 | 0 | case DeclSpec::SCS_static: return "static"; |
504 | 0 | case DeclSpec::SCS_auto: return "auto"; |
505 | 0 | case DeclSpec::SCS_register: return "register"; |
506 | 0 | case DeclSpec::SCS_private_extern: return "__private_extern__"; |
507 | 0 | case DeclSpec::SCS_mutable: return "mutable"; |
508 | 0 | } |
509 | 0 | llvm_unreachable("Unknown typespec!"); |
510 | 0 | } |
511 | | |
512 | 0 | const char *DeclSpec::getSpecifierName(DeclSpec::TSCS S) { |
513 | 0 | switch (S) { |
514 | 0 | case DeclSpec::TSCS_unspecified: return "unspecified"; |
515 | 0 | case DeclSpec::TSCS___thread: return "__thread"; |
516 | 0 | case DeclSpec::TSCS_thread_local: return "thread_local"; |
517 | 0 | case DeclSpec::TSCS__Thread_local: return "_Thread_local"; |
518 | 0 | } |
519 | 0 | llvm_unreachable("Unknown typespec!"); |
520 | 0 | } |
521 | | |
522 | 0 | const char *DeclSpec::getSpecifierName(TypeSpecifierWidth W) { |
523 | 0 | switch (W) { |
524 | 0 | case TypeSpecifierWidth::Unspecified: |
525 | 0 | return "unspecified"; |
526 | 0 | case TypeSpecifierWidth::Short: |
527 | 0 | return "short"; |
528 | 0 | case TypeSpecifierWidth::Long: |
529 | 0 | return "long"; |
530 | 0 | case TypeSpecifierWidth::LongLong: |
531 | 0 | return "long long"; |
532 | 0 | } |
533 | 0 | llvm_unreachable("Unknown typespec!"); |
534 | 0 | } |
535 | | |
536 | 0 | const char *DeclSpec::getSpecifierName(TSC C) { |
537 | 0 | switch (C) { |
538 | 0 | case TSC_unspecified: return "unspecified"; |
539 | 0 | case TSC_imaginary: return "imaginary"; |
540 | 0 | case TSC_complex: return "complex"; |
541 | 0 | } |
542 | 0 | llvm_unreachable("Unknown typespec!"); |
543 | 0 | } |
544 | | |
545 | 0 | const char *DeclSpec::getSpecifierName(TypeSpecifierSign S) { |
546 | 0 | switch (S) { |
547 | 0 | case TypeSpecifierSign::Unspecified: |
548 | 0 | return "unspecified"; |
549 | 0 | case TypeSpecifierSign::Signed: |
550 | 0 | return "signed"; |
551 | 0 | case TypeSpecifierSign::Unsigned: |
552 | 0 | return "unsigned"; |
553 | 0 | } |
554 | 0 | llvm_unreachable("Unknown typespec!"); |
555 | 0 | } |
556 | | |
557 | | const char *DeclSpec::getSpecifierName(DeclSpec::TST T, |
558 | 207 | const PrintingPolicy &Policy) { |
559 | 207 | switch (T) { |
560 | 207 | case DeclSpec::TST_unspecified: return "unspecified"; |
561 | 0 | case DeclSpec::TST_void: return "void"; |
562 | 0 | case DeclSpec::TST_char: return "char"; |
563 | 0 | case DeclSpec::TST_wchar: return Policy.MSWChar ? "__wchar_t" : "wchar_t"; |
564 | 0 | case DeclSpec::TST_char8: return "char8_t"; |
565 | 0 | case DeclSpec::TST_char16: return "char16_t"; |
566 | 0 | case DeclSpec::TST_char32: return "char32_t"; |
567 | 0 | case DeclSpec::TST_int: return "int"; |
568 | 0 | case DeclSpec::TST_int128: return "__int128"; |
569 | 0 | case DeclSpec::TST_bitint: return "_BitInt"; |
570 | 0 | case DeclSpec::TST_half: return "half"; |
571 | 0 | case DeclSpec::TST_float: return "float"; |
572 | 0 | case DeclSpec::TST_double: return "double"; |
573 | 0 | case DeclSpec::TST_accum: return "_Accum"; |
574 | 0 | case DeclSpec::TST_fract: return "_Fract"; |
575 | 0 | case DeclSpec::TST_float16: return "_Float16"; |
576 | 0 | case DeclSpec::TST_float128: return "__float128"; |
577 | 0 | case DeclSpec::TST_ibm128: return "__ibm128"; |
578 | 0 | case DeclSpec::TST_bool: return Policy.Bool ? "bool" : "_Bool"; |
579 | 0 | case DeclSpec::TST_decimal32: return "_Decimal32"; |
580 | 0 | case DeclSpec::TST_decimal64: return "_Decimal64"; |
581 | 0 | case DeclSpec::TST_decimal128: return "_Decimal128"; |
582 | 0 | case DeclSpec::TST_enum: return "enum"; |
583 | 0 | case DeclSpec::TST_class: return "class"; |
584 | 0 | case DeclSpec::TST_union: return "union"; |
585 | 0 | case DeclSpec::TST_struct: return "struct"; |
586 | 0 | case DeclSpec::TST_interface: return "__interface"; |
587 | 0 | case DeclSpec::TST_typename: return "type-name"; |
588 | 0 | case DeclSpec::TST_typeofType: |
589 | 0 | case DeclSpec::TST_typeofExpr: return "typeof"; |
590 | 0 | case DeclSpec::TST_typeof_unqualType: |
591 | 0 | case DeclSpec::TST_typeof_unqualExpr: return "typeof_unqual"; |
592 | 0 | case DeclSpec::TST_auto: return "auto"; |
593 | 0 | case DeclSpec::TST_auto_type: return "__auto_type"; |
594 | 0 | case DeclSpec::TST_decltype: return "(decltype)"; |
595 | 0 | case DeclSpec::TST_decltype_auto: return "decltype(auto)"; |
596 | 0 | #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ |
597 | 0 | case DeclSpec::TST_##Trait: \ |
598 | 0 | return "__" #Trait; |
599 | 0 | #include "clang/Basic/TransformTypeTraits.def" |
600 | 0 | case DeclSpec::TST_unknown_anytype: return "__unknown_anytype"; |
601 | 0 | case DeclSpec::TST_atomic: return "_Atomic"; |
602 | 0 | case DeclSpec::TST_BFloat16: return "__bf16"; |
603 | 0 | #define GENERIC_IMAGE_TYPE(ImgType, Id) \ |
604 | 0 | case DeclSpec::TST_##ImgType##_t: \ |
605 | 0 | return #ImgType "_t"; |
606 | 0 | #include "clang/Basic/OpenCLImageTypes.def" |
607 | 0 | case DeclSpec::TST_error: return "(error)"; |
608 | 207 | } |
609 | 0 | llvm_unreachable("Unknown typespec!"); |
610 | 0 | } |
611 | | |
612 | 0 | const char *DeclSpec::getSpecifierName(ConstexprSpecKind C) { |
613 | 0 | switch (C) { |
614 | 0 | case ConstexprSpecKind::Unspecified: |
615 | 0 | return "unspecified"; |
616 | 0 | case ConstexprSpecKind::Constexpr: |
617 | 0 | return "constexpr"; |
618 | 0 | case ConstexprSpecKind::Consteval: |
619 | 0 | return "consteval"; |
620 | 0 | case ConstexprSpecKind::Constinit: |
621 | 0 | return "constinit"; |
622 | 0 | } |
623 | 0 | llvm_unreachable("Unknown ConstexprSpecKind"); |
624 | 0 | } |
625 | | |
626 | 0 | const char *DeclSpec::getSpecifierName(TQ T) { |
627 | 0 | switch (T) { |
628 | 0 | case DeclSpec::TQ_unspecified: return "unspecified"; |
629 | 0 | case DeclSpec::TQ_const: return "const"; |
630 | 0 | case DeclSpec::TQ_restrict: return "restrict"; |
631 | 0 | case DeclSpec::TQ_volatile: return "volatile"; |
632 | 0 | case DeclSpec::TQ_atomic: return "_Atomic"; |
633 | 0 | case DeclSpec::TQ_unaligned: return "__unaligned"; |
634 | 0 | } |
635 | 0 | llvm_unreachable("Unknown typespec!"); |
636 | 0 | } |
637 | | |
638 | | bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc, |
639 | | const char *&PrevSpec, |
640 | | unsigned &DiagID, |
641 | 0 | const PrintingPolicy &Policy) { |
642 | | // OpenCL v1.1 s6.8g: "The extern, static, auto and register storage-class |
643 | | // specifiers are not supported. |
644 | | // It seems sensible to prohibit private_extern too |
645 | | // The cl_clang_storage_class_specifiers extension enables support for |
646 | | // these storage-class specifiers. |
647 | | // OpenCL v1.2 s6.8 changes this to "The auto and register storage-class |
648 | | // specifiers are not supported." |
649 | 0 | if (S.getLangOpts().OpenCL && |
650 | 0 | !S.getOpenCLOptions().isAvailableOption( |
651 | 0 | "cl_clang_storage_class_specifiers", S.getLangOpts())) { |
652 | 0 | switch (SC) { |
653 | 0 | case SCS_extern: |
654 | 0 | case SCS_private_extern: |
655 | 0 | case SCS_static: |
656 | 0 | if (S.getLangOpts().getOpenCLCompatibleVersion() < 120) { |
657 | 0 | DiagID = diag::err_opencl_unknown_type_specifier; |
658 | 0 | PrevSpec = getSpecifierName(SC); |
659 | 0 | return true; |
660 | 0 | } |
661 | 0 | break; |
662 | 0 | case SCS_auto: |
663 | 0 | case SCS_register: |
664 | 0 | DiagID = diag::err_opencl_unknown_type_specifier; |
665 | 0 | PrevSpec = getSpecifierName(SC); |
666 | 0 | return true; |
667 | 0 | default: |
668 | 0 | break; |
669 | 0 | } |
670 | 0 | } |
671 | | |
672 | 0 | if (StorageClassSpec != SCS_unspecified) { |
673 | | // Maybe this is an attempt to use C++11 'auto' outside of C++11 mode. |
674 | 0 | bool isInvalid = true; |
675 | 0 | if (TypeSpecType == TST_unspecified && S.getLangOpts().CPlusPlus) { |
676 | 0 | if (SC == SCS_auto) |
677 | 0 | return SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID, Policy); |
678 | 0 | if (StorageClassSpec == SCS_auto) { |
679 | 0 | isInvalid = SetTypeSpecType(TST_auto, StorageClassSpecLoc, |
680 | 0 | PrevSpec, DiagID, Policy); |
681 | 0 | assert(!isInvalid && "auto SCS -> TST recovery failed"); |
682 | 0 | } |
683 | 0 | } |
684 | | |
685 | | // Changing storage class is allowed only if the previous one |
686 | | // was the 'extern' that is part of a linkage specification and |
687 | | // the new storage class is 'typedef'. |
688 | 0 | if (isInvalid && |
689 | 0 | !(SCS_extern_in_linkage_spec && |
690 | 0 | StorageClassSpec == SCS_extern && |
691 | 0 | SC == SCS_typedef)) |
692 | 0 | return BadSpecifier(SC, (SCS)StorageClassSpec, PrevSpec, DiagID); |
693 | 0 | } |
694 | 0 | StorageClassSpec = SC; |
695 | 0 | StorageClassSpecLoc = Loc; |
696 | 0 | assert((unsigned)SC == StorageClassSpec && "SCS constants overflow bitfield"); |
697 | 0 | return false; |
698 | 0 | } |
699 | | |
700 | | bool DeclSpec::SetStorageClassSpecThread(TSCS TSC, SourceLocation Loc, |
701 | | const char *&PrevSpec, |
702 | 0 | unsigned &DiagID) { |
703 | 0 | if (ThreadStorageClassSpec != TSCS_unspecified) |
704 | 0 | return BadSpecifier(TSC, (TSCS)ThreadStorageClassSpec, PrevSpec, DiagID); |
705 | | |
706 | 0 | ThreadStorageClassSpec = TSC; |
707 | 0 | ThreadStorageClassSpecLoc = Loc; |
708 | 0 | return false; |
709 | 0 | } |
710 | | |
711 | | /// These methods set the specified attribute of the DeclSpec, but return true |
712 | | /// and ignore the request if invalid (e.g. "extern" then "auto" is |
713 | | /// specified). |
714 | | bool DeclSpec::SetTypeSpecWidth(TypeSpecifierWidth W, SourceLocation Loc, |
715 | | const char *&PrevSpec, unsigned &DiagID, |
716 | 0 | const PrintingPolicy &Policy) { |
717 | | // Overwrite TSWRange.Begin only if TypeSpecWidth was unspecified, so that |
718 | | // for 'long long' we will keep the source location of the first 'long'. |
719 | 0 | if (getTypeSpecWidth() == TypeSpecifierWidth::Unspecified) |
720 | 0 | TSWRange.setBegin(Loc); |
721 | | // Allow turning long -> long long. |
722 | 0 | else if (W != TypeSpecifierWidth::LongLong || |
723 | 0 | getTypeSpecWidth() != TypeSpecifierWidth::Long) |
724 | 0 | return BadSpecifier(W, getTypeSpecWidth(), PrevSpec, DiagID); |
725 | 0 | TypeSpecWidth = static_cast<unsigned>(W); |
726 | | // Remember location of the last 'long' |
727 | 0 | TSWRange.setEnd(Loc); |
728 | 0 | return false; |
729 | 0 | } |
730 | | |
731 | | bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc, |
732 | | const char *&PrevSpec, |
733 | 0 | unsigned &DiagID) { |
734 | 0 | if (TypeSpecComplex != TSC_unspecified) |
735 | 0 | return BadSpecifier(C, (TSC)TypeSpecComplex, PrevSpec, DiagID); |
736 | 0 | TypeSpecComplex = C; |
737 | 0 | TSCLoc = Loc; |
738 | 0 | return false; |
739 | 0 | } |
740 | | |
741 | | bool DeclSpec::SetTypeSpecSign(TypeSpecifierSign S, SourceLocation Loc, |
742 | 0 | const char *&PrevSpec, unsigned &DiagID) { |
743 | 0 | if (getTypeSpecSign() != TypeSpecifierSign::Unspecified) |
744 | 0 | return BadSpecifier(S, getTypeSpecSign(), PrevSpec, DiagID); |
745 | 0 | TypeSpecSign = static_cast<unsigned>(S); |
746 | 0 | TSSLoc = Loc; |
747 | 0 | return false; |
748 | 0 | } |
749 | | |
750 | | bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, |
751 | | const char *&PrevSpec, |
752 | | unsigned &DiagID, |
753 | | ParsedType Rep, |
754 | 0 | const PrintingPolicy &Policy) { |
755 | 0 | return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Policy); |
756 | 0 | } |
757 | | |
758 | | bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc, |
759 | | SourceLocation TagNameLoc, |
760 | | const char *&PrevSpec, |
761 | | unsigned &DiagID, |
762 | | ParsedType Rep, |
763 | 80 | const PrintingPolicy &Policy) { |
764 | 80 | assert(isTypeRep(T) && "T does not store a type"); |
765 | 0 | assert(Rep && "no type provided!"); |
766 | 80 | if (TypeSpecType == TST_error) |
767 | 0 | return false; |
768 | 80 | if (TypeSpecType != TST_unspecified) { |
769 | 0 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); |
770 | 0 | DiagID = diag::err_invalid_decl_spec_combination; |
771 | 0 | return true; |
772 | 0 | } |
773 | 80 | TypeSpecType = T; |
774 | 80 | TypeRep = Rep; |
775 | 80 | TSTLoc = TagKwLoc; |
776 | 80 | TSTNameLoc = TagNameLoc; |
777 | 80 | TypeSpecOwned = false; |
778 | 80 | return false; |
779 | 80 | } |
780 | | |
781 | | bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, |
782 | | const char *&PrevSpec, |
783 | | unsigned &DiagID, |
784 | | Expr *Rep, |
785 | 0 | const PrintingPolicy &Policy) { |
786 | 0 | assert(isExprRep(T) && "T does not store an expr"); |
787 | 0 | assert(Rep && "no expression provided!"); |
788 | 0 | if (TypeSpecType == TST_error) |
789 | 0 | return false; |
790 | 0 | if (TypeSpecType != TST_unspecified) { |
791 | 0 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); |
792 | 0 | DiagID = diag::err_invalid_decl_spec_combination; |
793 | 0 | return true; |
794 | 0 | } |
795 | 0 | TypeSpecType = T; |
796 | 0 | ExprRep = Rep; |
797 | 0 | TSTLoc = Loc; |
798 | 0 | TSTNameLoc = Loc; |
799 | 0 | TypeSpecOwned = false; |
800 | 0 | return false; |
801 | 0 | } |
802 | | |
803 | | bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, |
804 | | const char *&PrevSpec, |
805 | | unsigned &DiagID, |
806 | | Decl *Rep, bool Owned, |
807 | 0 | const PrintingPolicy &Policy) { |
808 | 0 | return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Owned, Policy); |
809 | 0 | } |
810 | | |
811 | | bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc, |
812 | | SourceLocation TagNameLoc, |
813 | | const char *&PrevSpec, |
814 | | unsigned &DiagID, |
815 | | Decl *Rep, bool Owned, |
816 | 0 | const PrintingPolicy &Policy) { |
817 | 0 | assert(isDeclRep(T) && "T does not store a decl"); |
818 | | // Unlike the other cases, we don't assert that we actually get a decl. |
819 | | |
820 | 0 | if (TypeSpecType == TST_error) |
821 | 0 | return false; |
822 | 0 | if (TypeSpecType != TST_unspecified) { |
823 | 0 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); |
824 | 0 | DiagID = diag::err_invalid_decl_spec_combination; |
825 | 0 | return true; |
826 | 0 | } |
827 | 0 | TypeSpecType = T; |
828 | 0 | DeclRep = Rep; |
829 | 0 | TSTLoc = TagKwLoc; |
830 | 0 | TSTNameLoc = TagNameLoc; |
831 | 0 | TypeSpecOwned = Owned && Rep != nullptr; |
832 | 0 | return false; |
833 | 0 | } |
834 | | |
835 | | bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, |
836 | | unsigned &DiagID, TemplateIdAnnotation *Rep, |
837 | 0 | const PrintingPolicy &Policy) { |
838 | 0 | assert(T == TST_auto || T == TST_decltype_auto); |
839 | 0 | ConstrainedAuto = true; |
840 | 0 | TemplateIdRep = Rep; |
841 | 0 | return SetTypeSpecType(T, Loc, PrevSpec, DiagID, Policy); |
842 | 0 | } |
843 | | |
844 | | bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, |
845 | | const char *&PrevSpec, |
846 | | unsigned &DiagID, |
847 | 0 | const PrintingPolicy &Policy) { |
848 | 0 | assert(!isDeclRep(T) && !isTypeRep(T) && !isExprRep(T) && |
849 | 0 | "rep required for these type-spec kinds!"); |
850 | 0 | if (TypeSpecType == TST_error) |
851 | 0 | return false; |
852 | 0 | if (TypeSpecType != TST_unspecified) { |
853 | 0 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); |
854 | 0 | DiagID = diag::err_invalid_decl_spec_combination; |
855 | 0 | return true; |
856 | 0 | } |
857 | 0 | TSTLoc = Loc; |
858 | 0 | TSTNameLoc = Loc; |
859 | 0 | if (TypeAltiVecVector && (T == TST_bool) && !TypeAltiVecBool) { |
860 | 0 | TypeAltiVecBool = true; |
861 | 0 | return false; |
862 | 0 | } |
863 | 0 | TypeSpecType = T; |
864 | 0 | TypeSpecOwned = false; |
865 | 0 | return false; |
866 | 0 | } |
867 | | |
868 | | bool DeclSpec::SetTypeSpecSat(SourceLocation Loc, const char *&PrevSpec, |
869 | 0 | unsigned &DiagID) { |
870 | | // Cannot set twice |
871 | 0 | if (TypeSpecSat) { |
872 | 0 | DiagID = diag::warn_duplicate_declspec; |
873 | 0 | PrevSpec = "_Sat"; |
874 | 0 | return true; |
875 | 0 | } |
876 | 0 | TypeSpecSat = true; |
877 | 0 | TSSatLoc = Loc; |
878 | 0 | return false; |
879 | 0 | } |
880 | | |
881 | | bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, |
882 | | const char *&PrevSpec, unsigned &DiagID, |
883 | 0 | const PrintingPolicy &Policy) { |
884 | 0 | if (TypeSpecType == TST_error) |
885 | 0 | return false; |
886 | 0 | if (TypeSpecType != TST_unspecified) { |
887 | 0 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); |
888 | 0 | DiagID = diag::err_invalid_vector_decl_spec_combination; |
889 | 0 | return true; |
890 | 0 | } |
891 | 0 | TypeAltiVecVector = isAltiVecVector; |
892 | 0 | AltiVecLoc = Loc; |
893 | 0 | return false; |
894 | 0 | } |
895 | | |
896 | | bool DeclSpec::SetTypePipe(bool isPipe, SourceLocation Loc, |
897 | | const char *&PrevSpec, unsigned &DiagID, |
898 | 0 | const PrintingPolicy &Policy) { |
899 | 0 | if (TypeSpecType == TST_error) |
900 | 0 | return false; |
901 | 0 | if (TypeSpecType != TST_unspecified) { |
902 | 0 | PrevSpec = DeclSpec::getSpecifierName((TST)TypeSpecType, Policy); |
903 | 0 | DiagID = diag::err_invalid_decl_spec_combination; |
904 | 0 | return true; |
905 | 0 | } |
906 | | |
907 | 0 | if (isPipe) { |
908 | 0 | TypeSpecPipe = static_cast<unsigned>(TypeSpecifiersPipe::Pipe); |
909 | 0 | } |
910 | 0 | return false; |
911 | 0 | } |
912 | | |
913 | | bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, |
914 | | const char *&PrevSpec, unsigned &DiagID, |
915 | 0 | const PrintingPolicy &Policy) { |
916 | 0 | if (TypeSpecType == TST_error) |
917 | 0 | return false; |
918 | 0 | if (!TypeAltiVecVector || TypeAltiVecPixel || |
919 | 0 | (TypeSpecType != TST_unspecified)) { |
920 | 0 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); |
921 | 0 | DiagID = diag::err_invalid_pixel_decl_spec_combination; |
922 | 0 | return true; |
923 | 0 | } |
924 | 0 | TypeAltiVecPixel = isAltiVecPixel; |
925 | 0 | TSTLoc = Loc; |
926 | 0 | TSTNameLoc = Loc; |
927 | 0 | return false; |
928 | 0 | } |
929 | | |
930 | | bool DeclSpec::SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc, |
931 | | const char *&PrevSpec, unsigned &DiagID, |
932 | 0 | const PrintingPolicy &Policy) { |
933 | 0 | if (TypeSpecType == TST_error) |
934 | 0 | return false; |
935 | 0 | if (!TypeAltiVecVector || TypeAltiVecBool || |
936 | 0 | (TypeSpecType != TST_unspecified)) { |
937 | 0 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); |
938 | 0 | DiagID = diag::err_invalid_vector_bool_decl_spec; |
939 | 0 | return true; |
940 | 0 | } |
941 | 0 | TypeAltiVecBool = isAltiVecBool; |
942 | 0 | TSTLoc = Loc; |
943 | 0 | TSTNameLoc = Loc; |
944 | 0 | return false; |
945 | 0 | } |
946 | | |
947 | 10.2k | bool DeclSpec::SetTypeSpecError() { |
948 | 10.2k | TypeSpecType = TST_error; |
949 | 10.2k | TypeSpecOwned = false; |
950 | 10.2k | TSTLoc = SourceLocation(); |
951 | 10.2k | TSTNameLoc = SourceLocation(); |
952 | 10.2k | return false; |
953 | 10.2k | } |
954 | | |
955 | | bool DeclSpec::SetBitIntType(SourceLocation KWLoc, Expr *BitsExpr, |
956 | | const char *&PrevSpec, unsigned &DiagID, |
957 | 0 | const PrintingPolicy &Policy) { |
958 | 0 | assert(BitsExpr && "no expression provided!"); |
959 | 0 | if (TypeSpecType == TST_error) |
960 | 0 | return false; |
961 | | |
962 | 0 | if (TypeSpecType != TST_unspecified) { |
963 | 0 | PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy); |
964 | 0 | DiagID = diag::err_invalid_decl_spec_combination; |
965 | 0 | return true; |
966 | 0 | } |
967 | | |
968 | 0 | TypeSpecType = TST_bitint; |
969 | 0 | ExprRep = BitsExpr; |
970 | 0 | TSTLoc = KWLoc; |
971 | 0 | TSTNameLoc = KWLoc; |
972 | 0 | TypeSpecOwned = false; |
973 | 0 | return false; |
974 | 0 | } |
975 | | |
976 | | bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, |
977 | 0 | unsigned &DiagID, const LangOptions &Lang) { |
978 | | // Duplicates are permitted in C99 onwards, but are not permitted in C89 or |
979 | | // C++. However, since this is likely not what the user intended, we will |
980 | | // always warn. We do not need to set the qualifier's location since we |
981 | | // already have it. |
982 | 0 | if (TypeQualifiers & T) { |
983 | 0 | bool IsExtension = true; |
984 | 0 | if (Lang.C99) |
985 | 0 | IsExtension = false; |
986 | 0 | return BadSpecifier(T, T, PrevSpec, DiagID, IsExtension); |
987 | 0 | } |
988 | | |
989 | 0 | return SetTypeQual(T, Loc); |
990 | 0 | } |
991 | | |
992 | 0 | bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc) { |
993 | 0 | TypeQualifiers |= T; |
994 | |
|
995 | 0 | switch (T) { |
996 | 0 | case TQ_unspecified: break; |
997 | 0 | case TQ_const: TQ_constLoc = Loc; return false; |
998 | 0 | case TQ_restrict: TQ_restrictLoc = Loc; return false; |
999 | 0 | case TQ_volatile: TQ_volatileLoc = Loc; return false; |
1000 | 0 | case TQ_unaligned: TQ_unalignedLoc = Loc; return false; |
1001 | 0 | case TQ_atomic: TQ_atomicLoc = Loc; return false; |
1002 | 0 | } |
1003 | | |
1004 | 0 | llvm_unreachable("Unknown type qualifier!"); |
1005 | 0 | } |
1006 | | |
1007 | | bool DeclSpec::setFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec, |
1008 | 0 | unsigned &DiagID) { |
1009 | | // 'inline inline' is ok. However, since this is likely not what the user |
1010 | | // intended, we will always warn, similar to duplicates of type qualifiers. |
1011 | 0 | if (FS_inline_specified) { |
1012 | 0 | DiagID = diag::warn_duplicate_declspec; |
1013 | 0 | PrevSpec = "inline"; |
1014 | 0 | return true; |
1015 | 0 | } |
1016 | 0 | FS_inline_specified = true; |
1017 | 0 | FS_inlineLoc = Loc; |
1018 | 0 | return false; |
1019 | 0 | } |
1020 | | |
1021 | | bool DeclSpec::setFunctionSpecForceInline(SourceLocation Loc, const char *&PrevSpec, |
1022 | 0 | unsigned &DiagID) { |
1023 | 0 | if (FS_forceinline_specified) { |
1024 | 0 | DiagID = diag::warn_duplicate_declspec; |
1025 | 0 | PrevSpec = "__forceinline"; |
1026 | 0 | return true; |
1027 | 0 | } |
1028 | 0 | FS_forceinline_specified = true; |
1029 | 0 | FS_forceinlineLoc = Loc; |
1030 | 0 | return false; |
1031 | 0 | } |
1032 | | |
1033 | | bool DeclSpec::setFunctionSpecVirtual(SourceLocation Loc, |
1034 | | const char *&PrevSpec, |
1035 | 0 | unsigned &DiagID) { |
1036 | | // 'virtual virtual' is ok, but warn as this is likely not what the user |
1037 | | // intended. |
1038 | 0 | if (FS_virtual_specified) { |
1039 | 0 | DiagID = diag::warn_duplicate_declspec; |
1040 | 0 | PrevSpec = "virtual"; |
1041 | 0 | return true; |
1042 | 0 | } |
1043 | 0 | FS_virtual_specified = true; |
1044 | 0 | FS_virtualLoc = Loc; |
1045 | 0 | return false; |
1046 | 0 | } |
1047 | | |
1048 | | bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc, |
1049 | | const char *&PrevSpec, unsigned &DiagID, |
1050 | | ExplicitSpecifier ExplicitSpec, |
1051 | 0 | SourceLocation CloseParenLoc) { |
1052 | | // 'explicit explicit' is ok, but warn as this is likely not what the user |
1053 | | // intended. |
1054 | 0 | if (hasExplicitSpecifier()) { |
1055 | 0 | DiagID = (ExplicitSpec.getExpr() || FS_explicit_specifier.getExpr()) |
1056 | 0 | ? diag::err_duplicate_declspec |
1057 | 0 | : diag::ext_warn_duplicate_declspec; |
1058 | 0 | PrevSpec = "explicit"; |
1059 | 0 | return true; |
1060 | 0 | } |
1061 | 0 | FS_explicit_specifier = ExplicitSpec; |
1062 | 0 | FS_explicitLoc = Loc; |
1063 | 0 | FS_explicitCloseParenLoc = CloseParenLoc; |
1064 | 0 | return false; |
1065 | 0 | } |
1066 | | |
1067 | | bool DeclSpec::setFunctionSpecNoreturn(SourceLocation Loc, |
1068 | | const char *&PrevSpec, |
1069 | 0 | unsigned &DiagID) { |
1070 | | // '_Noreturn _Noreturn' is ok, but warn as this is likely not what the user |
1071 | | // intended. |
1072 | 0 | if (FS_noreturn_specified) { |
1073 | 0 | DiagID = diag::warn_duplicate_declspec; |
1074 | 0 | PrevSpec = "_Noreturn"; |
1075 | 0 | return true; |
1076 | 0 | } |
1077 | 0 | FS_noreturn_specified = true; |
1078 | 0 | FS_noreturnLoc = Loc; |
1079 | 0 | return false; |
1080 | 0 | } |
1081 | | |
1082 | | bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, |
1083 | 0 | unsigned &DiagID) { |
1084 | 0 | if (Friend_specified) { |
1085 | 0 | PrevSpec = "friend"; |
1086 | | // Keep the later location, so that we can later diagnose ill-formed |
1087 | | // declarations like 'friend class X friend;'. Per [class.friend]p3, |
1088 | | // 'friend' must be the first token in a friend declaration that is |
1089 | | // not a function declaration. |
1090 | 0 | FriendLoc = Loc; |
1091 | 0 | DiagID = diag::warn_duplicate_declspec; |
1092 | 0 | return true; |
1093 | 0 | } |
1094 | | |
1095 | 0 | Friend_specified = true; |
1096 | 0 | FriendLoc = Loc; |
1097 | 0 | return false; |
1098 | 0 | } |
1099 | | |
1100 | | bool DeclSpec::setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec, |
1101 | 0 | unsigned &DiagID) { |
1102 | 0 | if (isModulePrivateSpecified()) { |
1103 | 0 | PrevSpec = "__module_private__"; |
1104 | 0 | DiagID = diag::ext_warn_duplicate_declspec; |
1105 | 0 | return true; |
1106 | 0 | } |
1107 | | |
1108 | 0 | ModulePrivateLoc = Loc; |
1109 | 0 | return false; |
1110 | 0 | } |
1111 | | |
1112 | | bool DeclSpec::SetConstexprSpec(ConstexprSpecKind ConstexprKind, |
1113 | | SourceLocation Loc, const char *&PrevSpec, |
1114 | 0 | unsigned &DiagID) { |
1115 | 0 | if (getConstexprSpecifier() != ConstexprSpecKind::Unspecified) |
1116 | 0 | return BadSpecifier(ConstexprKind, getConstexprSpecifier(), PrevSpec, |
1117 | 0 | DiagID); |
1118 | 0 | ConstexprSpecifier = static_cast<unsigned>(ConstexprKind); |
1119 | 0 | ConstexprLoc = Loc; |
1120 | 0 | return false; |
1121 | 0 | } |
1122 | | |
1123 | 25.1k | void DeclSpec::SaveWrittenBuiltinSpecs() { |
1124 | 25.1k | writtenBS.Sign = static_cast<int>(getTypeSpecSign()); |
1125 | 25.1k | writtenBS.Width = static_cast<int>(getTypeSpecWidth()); |
1126 | 25.1k | writtenBS.Type = getTypeSpecType(); |
1127 | | // Search the list of attributes for the presence of a mode attribute. |
1128 | 25.1k | writtenBS.ModeAttr = getAttributes().hasAttribute(ParsedAttr::AT_Mode); |
1129 | 25.1k | } |
1130 | | |
1131 | | /// Finish - This does final analysis of the declspec, rejecting things like |
1132 | | /// "_Imaginary" (lacking an FP type). After calling this method, DeclSpec is |
1133 | | /// guaranteed to be self-consistent, even if an error occurred. |
1134 | 25.1k | void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { |
1135 | | // Before possibly changing their values, save specs as written. |
1136 | 25.1k | SaveWrittenBuiltinSpecs(); |
1137 | | |
1138 | | // Check the type specifier components first. No checking for an invalid |
1139 | | // type. |
1140 | 25.1k | if (TypeSpecType == TST_error) |
1141 | 10.2k | return; |
1142 | | |
1143 | | // If decltype(auto) is used, no other type specifiers are permitted. |
1144 | 14.8k | if (TypeSpecType == TST_decltype_auto && |
1145 | 14.8k | (getTypeSpecWidth() != TypeSpecifierWidth::Unspecified || |
1146 | 0 | TypeSpecComplex != TSC_unspecified || |
1147 | 0 | getTypeSpecSign() != TypeSpecifierSign::Unspecified || |
1148 | 0 | TypeAltiVecVector || TypeAltiVecPixel || TypeAltiVecBool || |
1149 | 0 | TypeQualifiers)) { |
1150 | 0 | const unsigned NumLocs = 9; |
1151 | 0 | SourceLocation ExtraLocs[NumLocs] = { |
1152 | 0 | TSWRange.getBegin(), TSCLoc, TSSLoc, |
1153 | 0 | AltiVecLoc, TQ_constLoc, TQ_restrictLoc, |
1154 | 0 | TQ_volatileLoc, TQ_atomicLoc, TQ_unalignedLoc}; |
1155 | 0 | FixItHint Hints[NumLocs]; |
1156 | 0 | SourceLocation FirstLoc; |
1157 | 0 | for (unsigned I = 0; I != NumLocs; ++I) { |
1158 | 0 | if (ExtraLocs[I].isValid()) { |
1159 | 0 | if (FirstLoc.isInvalid() || |
1160 | 0 | S.getSourceManager().isBeforeInTranslationUnit(ExtraLocs[I], |
1161 | 0 | FirstLoc)) |
1162 | 0 | FirstLoc = ExtraLocs[I]; |
1163 | 0 | Hints[I] = FixItHint::CreateRemoval(ExtraLocs[I]); |
1164 | 0 | } |
1165 | 0 | } |
1166 | 0 | TypeSpecWidth = static_cast<unsigned>(TypeSpecifierWidth::Unspecified); |
1167 | 0 | TypeSpecComplex = TSC_unspecified; |
1168 | 0 | TypeSpecSign = static_cast<unsigned>(TypeSpecifierSign::Unspecified); |
1169 | 0 | TypeAltiVecVector = TypeAltiVecPixel = TypeAltiVecBool = false; |
1170 | 0 | TypeQualifiers = 0; |
1171 | 0 | S.Diag(TSTLoc, diag::err_decltype_auto_cannot_be_combined) |
1172 | 0 | << Hints[0] << Hints[1] << Hints[2] << Hints[3] |
1173 | 0 | << Hints[4] << Hints[5] << Hints[6] << Hints[7]; |
1174 | 0 | } |
1175 | | |
1176 | | // Validate and finalize AltiVec vector declspec. |
1177 | 14.8k | if (TypeAltiVecVector) { |
1178 | | // No vector long long without VSX (or ZVector). |
1179 | 0 | if ((getTypeSpecWidth() == TypeSpecifierWidth::LongLong) && |
1180 | 0 | !S.Context.getTargetInfo().hasFeature("vsx") && |
1181 | 0 | !S.getLangOpts().ZVector) |
1182 | 0 | S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_long_long_decl_spec); |
1183 | | |
1184 | | // No vector __int128 prior to Power8. |
1185 | 0 | if ((TypeSpecType == TST_int128) && |
1186 | 0 | !S.Context.getTargetInfo().hasFeature("power8-vector")) |
1187 | 0 | S.Diag(TSTLoc, diag::err_invalid_vector_int128_decl_spec); |
1188 | |
|
1189 | 0 | if (TypeAltiVecBool) { |
1190 | | // Sign specifiers are not allowed with vector bool. (PIM 2.1) |
1191 | 0 | if (getTypeSpecSign() != TypeSpecifierSign::Unspecified) { |
1192 | 0 | S.Diag(TSSLoc, diag::err_invalid_vector_bool_decl_spec) |
1193 | 0 | << getSpecifierName(getTypeSpecSign()); |
1194 | 0 | } |
1195 | | // Only char/int are valid with vector bool prior to Power10. |
1196 | | // Power10 adds instructions that produce vector bool data |
1197 | | // for quadwords as well so allow vector bool __int128. |
1198 | 0 | if (((TypeSpecType != TST_unspecified) && (TypeSpecType != TST_char) && |
1199 | 0 | (TypeSpecType != TST_int) && (TypeSpecType != TST_int128)) || |
1200 | 0 | TypeAltiVecPixel) { |
1201 | 0 | S.Diag(TSTLoc, diag::err_invalid_vector_bool_decl_spec) |
1202 | 0 | << (TypeAltiVecPixel ? "__pixel" : |
1203 | 0 | getSpecifierName((TST)TypeSpecType, Policy)); |
1204 | 0 | } |
1205 | | // vector bool __int128 requires Power10. |
1206 | 0 | if ((TypeSpecType == TST_int128) && |
1207 | 0 | (!S.Context.getTargetInfo().hasFeature("power10-vector"))) |
1208 | 0 | S.Diag(TSTLoc, diag::err_invalid_vector_bool_int128_decl_spec); |
1209 | | |
1210 | | // Only 'short' and 'long long' are valid with vector bool. (PIM 2.1) |
1211 | 0 | if ((getTypeSpecWidth() != TypeSpecifierWidth::Unspecified) && |
1212 | 0 | (getTypeSpecWidth() != TypeSpecifierWidth::Short) && |
1213 | 0 | (getTypeSpecWidth() != TypeSpecifierWidth::LongLong)) |
1214 | 0 | S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_bool_decl_spec) |
1215 | 0 | << getSpecifierName(getTypeSpecWidth()); |
1216 | | |
1217 | | // Elements of vector bool are interpreted as unsigned. (PIM 2.1) |
1218 | 0 | if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) || |
1219 | 0 | (TypeSpecType == TST_int128) || |
1220 | 0 | (getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)) |
1221 | 0 | TypeSpecSign = static_cast<unsigned>(TypeSpecifierSign::Unsigned); |
1222 | 0 | } else if (TypeSpecType == TST_double) { |
1223 | | // vector long double and vector long long double are never allowed. |
1224 | | // vector double is OK for Power7 and later, and ZVector. |
1225 | 0 | if (getTypeSpecWidth() == TypeSpecifierWidth::Long || |
1226 | 0 | getTypeSpecWidth() == TypeSpecifierWidth::LongLong) |
1227 | 0 | S.Diag(TSWRange.getBegin(), |
1228 | 0 | diag::err_invalid_vector_long_double_decl_spec); |
1229 | 0 | else if (!S.Context.getTargetInfo().hasFeature("vsx") && |
1230 | 0 | !S.getLangOpts().ZVector) |
1231 | 0 | S.Diag(TSTLoc, diag::err_invalid_vector_double_decl_spec); |
1232 | 0 | } else if (TypeSpecType == TST_float) { |
1233 | | // vector float is unsupported for ZVector unless we have the |
1234 | | // vector-enhancements facility 1 (ISA revision 12). |
1235 | 0 | if (S.getLangOpts().ZVector && |
1236 | 0 | !S.Context.getTargetInfo().hasFeature("arch12")) |
1237 | 0 | S.Diag(TSTLoc, diag::err_invalid_vector_float_decl_spec); |
1238 | 0 | } else if (getTypeSpecWidth() == TypeSpecifierWidth::Long) { |
1239 | | // Vector long is unsupported for ZVector, or without VSX, and deprecated |
1240 | | // for AltiVec. |
1241 | | // It has also been historically deprecated on AIX (as an alias for |
1242 | | // "vector int" in both 32-bit and 64-bit modes). It was then made |
1243 | | // unsupported in the Clang-based XL compiler since the deprecated type |
1244 | | // has a number of conflicting semantics and continuing to support it |
1245 | | // is a disservice to users. |
1246 | 0 | if (S.getLangOpts().ZVector || |
1247 | 0 | !S.Context.getTargetInfo().hasFeature("vsx") || |
1248 | 0 | S.Context.getTargetInfo().getTriple().isOSAIX()) |
1249 | 0 | S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_long_decl_spec); |
1250 | 0 | else |
1251 | 0 | S.Diag(TSWRange.getBegin(), |
1252 | 0 | diag::warn_vector_long_decl_spec_combination) |
1253 | 0 | << getSpecifierName((TST)TypeSpecType, Policy); |
1254 | 0 | } |
1255 | |
|
1256 | 0 | if (TypeAltiVecPixel) { |
1257 | | //TODO: perform validation |
1258 | 0 | TypeSpecType = TST_int; |
1259 | 0 | TypeSpecSign = static_cast<unsigned>(TypeSpecifierSign::Unsigned); |
1260 | 0 | TypeSpecWidth = static_cast<unsigned>(TypeSpecifierWidth::Short); |
1261 | 0 | TypeSpecOwned = false; |
1262 | 0 | } |
1263 | 0 | } |
1264 | | |
1265 | 14.8k | bool IsFixedPointType = |
1266 | 14.8k | TypeSpecType == TST_accum || TypeSpecType == TST_fract; |
1267 | | |
1268 | | // signed/unsigned are only valid with int/char/wchar_t/_Accum. |
1269 | 14.8k | if (getTypeSpecSign() != TypeSpecifierSign::Unspecified) { |
1270 | 0 | if (TypeSpecType == TST_unspecified) |
1271 | 0 | TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int. |
1272 | 0 | else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 && |
1273 | 0 | TypeSpecType != TST_char && TypeSpecType != TST_wchar && |
1274 | 0 | !IsFixedPointType && TypeSpecType != TST_bitint) { |
1275 | 0 | S.Diag(TSSLoc, diag::err_invalid_sign_spec) |
1276 | 0 | << getSpecifierName((TST)TypeSpecType, Policy); |
1277 | | // signed double -> double. |
1278 | 0 | TypeSpecSign = static_cast<unsigned>(TypeSpecifierSign::Unspecified); |
1279 | 0 | } |
1280 | 0 | } |
1281 | | |
1282 | | // Validate the width of the type. |
1283 | 14.8k | switch (getTypeSpecWidth()) { |
1284 | 14.8k | case TypeSpecifierWidth::Unspecified: |
1285 | 14.8k | break; |
1286 | 0 | case TypeSpecifierWidth::Short: // short int |
1287 | 0 | case TypeSpecifierWidth::LongLong: // long long int |
1288 | 0 | if (TypeSpecType == TST_unspecified) |
1289 | 0 | TypeSpecType = TST_int; // short -> short int, long long -> long long int. |
1290 | 0 | else if (!(TypeSpecType == TST_int || |
1291 | 0 | (IsFixedPointType && |
1292 | 0 | getTypeSpecWidth() != TypeSpecifierWidth::LongLong))) { |
1293 | 0 | S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec) |
1294 | 0 | << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy); |
1295 | 0 | TypeSpecType = TST_int; |
1296 | 0 | TypeSpecSat = false; |
1297 | 0 | TypeSpecOwned = false; |
1298 | 0 | } |
1299 | 0 | break; |
1300 | 0 | case TypeSpecifierWidth::Long: // long double, long int |
1301 | 0 | if (TypeSpecType == TST_unspecified) |
1302 | 0 | TypeSpecType = TST_int; // long -> long int. |
1303 | 0 | else if (TypeSpecType != TST_int && TypeSpecType != TST_double && |
1304 | 0 | !IsFixedPointType) { |
1305 | 0 | S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec) |
1306 | 0 | << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy); |
1307 | 0 | TypeSpecType = TST_int; |
1308 | 0 | TypeSpecSat = false; |
1309 | 0 | TypeSpecOwned = false; |
1310 | 0 | } |
1311 | 0 | break; |
1312 | 14.8k | } |
1313 | | |
1314 | | // TODO: if the implementation does not implement _Complex or _Imaginary, |
1315 | | // disallow their use. Need information about the backend. |
1316 | 14.8k | if (TypeSpecComplex != TSC_unspecified) { |
1317 | 0 | if (TypeSpecType == TST_unspecified) { |
1318 | 0 | S.Diag(TSCLoc, diag::ext_plain_complex) |
1319 | 0 | << FixItHint::CreateInsertion( |
1320 | 0 | S.getLocForEndOfToken(getTypeSpecComplexLoc()), |
1321 | 0 | " double"); |
1322 | 0 | TypeSpecType = TST_double; // _Complex -> _Complex double. |
1323 | 0 | } else if (TypeSpecType == TST_int || TypeSpecType == TST_char || |
1324 | 0 | TypeSpecType == TST_bitint) { |
1325 | | // Note that this intentionally doesn't include _Complex _Bool. |
1326 | 0 | if (!S.getLangOpts().CPlusPlus) |
1327 | 0 | S.Diag(TSTLoc, diag::ext_integer_complex); |
1328 | 0 | } else if (TypeSpecType != TST_float && TypeSpecType != TST_double && |
1329 | 0 | TypeSpecType != TST_float128 && TypeSpecType != TST_float16 && |
1330 | 0 | TypeSpecType != TST_ibm128) { |
1331 | | // FIXME: __fp16? |
1332 | 0 | S.Diag(TSCLoc, diag::err_invalid_complex_spec) |
1333 | 0 | << getSpecifierName((TST)TypeSpecType, Policy); |
1334 | 0 | TypeSpecComplex = TSC_unspecified; |
1335 | 0 | } |
1336 | 0 | } |
1337 | | |
1338 | | // C11 6.7.1/3, C++11 [dcl.stc]p1, GNU TLS: __thread, thread_local and |
1339 | | // _Thread_local can only appear with the 'static' and 'extern' storage class |
1340 | | // specifiers. We also allow __private_extern__ as an extension. |
1341 | 14.8k | if (ThreadStorageClassSpec != TSCS_unspecified) { |
1342 | 0 | switch (StorageClassSpec) { |
1343 | 0 | case SCS_unspecified: |
1344 | 0 | case SCS_extern: |
1345 | 0 | case SCS_private_extern: |
1346 | 0 | case SCS_static: |
1347 | 0 | break; |
1348 | 0 | default: |
1349 | 0 | if (S.getSourceManager().isBeforeInTranslationUnit( |
1350 | 0 | getThreadStorageClassSpecLoc(), getStorageClassSpecLoc())) |
1351 | 0 | S.Diag(getStorageClassSpecLoc(), |
1352 | 0 | diag::err_invalid_decl_spec_combination) |
1353 | 0 | << DeclSpec::getSpecifierName(getThreadStorageClassSpec()) |
1354 | 0 | << SourceRange(getThreadStorageClassSpecLoc()); |
1355 | 0 | else |
1356 | 0 | S.Diag(getThreadStorageClassSpecLoc(), |
1357 | 0 | diag::err_invalid_decl_spec_combination) |
1358 | 0 | << DeclSpec::getSpecifierName(getStorageClassSpec()) |
1359 | 0 | << SourceRange(getStorageClassSpecLoc()); |
1360 | | // Discard the thread storage class specifier to recover. |
1361 | 0 | ThreadStorageClassSpec = TSCS_unspecified; |
1362 | 0 | ThreadStorageClassSpecLoc = SourceLocation(); |
1363 | 0 | } |
1364 | 0 | } |
1365 | | |
1366 | | // If no type specifier was provided and we're parsing a language where |
1367 | | // the type specifier is not optional, but we got 'auto' as a storage |
1368 | | // class specifier, then assume this is an attempt to use C++0x's 'auto' |
1369 | | // type specifier. |
1370 | 14.8k | if (S.getLangOpts().CPlusPlus && |
1371 | 14.8k | TypeSpecType == TST_unspecified && StorageClassSpec == SCS_auto) { |
1372 | 0 | TypeSpecType = TST_auto; |
1373 | 0 | StorageClassSpec = SCS_unspecified; |
1374 | 0 | TSTLoc = TSTNameLoc = StorageClassSpecLoc; |
1375 | 0 | StorageClassSpecLoc = SourceLocation(); |
1376 | 0 | } |
1377 | | // Diagnose if we've recovered from an ill-formed 'auto' storage class |
1378 | | // specifier in a pre-C++11 dialect of C++ or in a pre-C23 dialect of C. |
1379 | 14.8k | if (!S.getLangOpts().CPlusPlus11 && !S.getLangOpts().C23 && |
1380 | 14.8k | TypeSpecType == TST_auto) |
1381 | 0 | S.Diag(TSTLoc, diag::ext_auto_type_specifier); |
1382 | 14.8k | if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11 && |
1383 | 14.8k | StorageClassSpec == SCS_auto) |
1384 | 0 | S.Diag(StorageClassSpecLoc, diag::warn_auto_storage_class) |
1385 | 0 | << FixItHint::CreateRemoval(StorageClassSpecLoc); |
1386 | 14.8k | if (TypeSpecType == TST_char8) |
1387 | 0 | S.Diag(TSTLoc, diag::warn_cxx17_compat_unicode_type); |
1388 | 14.8k | else if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32) |
1389 | 0 | S.Diag(TSTLoc, diag::warn_cxx98_compat_unicode_type) |
1390 | 0 | << (TypeSpecType == TST_char16 ? "char16_t" : "char32_t"); |
1391 | 14.8k | if (getConstexprSpecifier() == ConstexprSpecKind::Constexpr) |
1392 | 0 | S.Diag(ConstexprLoc, diag::warn_cxx98_compat_constexpr); |
1393 | 14.8k | else if (getConstexprSpecifier() == ConstexprSpecKind::Consteval) |
1394 | 0 | S.Diag(ConstexprLoc, diag::warn_cxx20_compat_consteval); |
1395 | 14.8k | else if (getConstexprSpecifier() == ConstexprSpecKind::Constinit) |
1396 | 0 | S.Diag(ConstexprLoc, diag::warn_cxx20_compat_constinit); |
1397 | | // C++ [class.friend]p6: |
1398 | | // No storage-class-specifier shall appear in the decl-specifier-seq |
1399 | | // of a friend declaration. |
1400 | 14.8k | if (isFriendSpecified() && |
1401 | 14.8k | (getStorageClassSpec() || getThreadStorageClassSpec())) { |
1402 | 0 | SmallString<32> SpecName; |
1403 | 0 | SourceLocation SCLoc; |
1404 | 0 | FixItHint StorageHint, ThreadHint; |
1405 | |
|
1406 | 0 | if (DeclSpec::SCS SC = getStorageClassSpec()) { |
1407 | 0 | SpecName = getSpecifierName(SC); |
1408 | 0 | SCLoc = getStorageClassSpecLoc(); |
1409 | 0 | StorageHint = FixItHint::CreateRemoval(SCLoc); |
1410 | 0 | } |
1411 | |
|
1412 | 0 | if (DeclSpec::TSCS TSC = getThreadStorageClassSpec()) { |
1413 | 0 | if (!SpecName.empty()) SpecName += " "; |
1414 | 0 | SpecName += getSpecifierName(TSC); |
1415 | 0 | SCLoc = getThreadStorageClassSpecLoc(); |
1416 | 0 | ThreadHint = FixItHint::CreateRemoval(SCLoc); |
1417 | 0 | } |
1418 | |
|
1419 | 0 | S.Diag(SCLoc, diag::err_friend_decl_spec) |
1420 | 0 | << SpecName << StorageHint << ThreadHint; |
1421 | |
|
1422 | 0 | ClearStorageClassSpecs(); |
1423 | 0 | } |
1424 | | |
1425 | | // C++11 [dcl.fct.spec]p5: |
1426 | | // The virtual specifier shall be used only in the initial |
1427 | | // declaration of a non-static class member function; |
1428 | | // C++11 [dcl.fct.spec]p6: |
1429 | | // The explicit specifier shall be used only in the declaration of |
1430 | | // a constructor or conversion function within its class |
1431 | | // definition; |
1432 | 14.8k | if (isFriendSpecified() && (isVirtualSpecified() || hasExplicitSpecifier())) { |
1433 | 0 | StringRef Keyword; |
1434 | 0 | FixItHint Hint; |
1435 | 0 | SourceLocation SCLoc; |
1436 | |
|
1437 | 0 | if (isVirtualSpecified()) { |
1438 | 0 | Keyword = "virtual"; |
1439 | 0 | SCLoc = getVirtualSpecLoc(); |
1440 | 0 | Hint = FixItHint::CreateRemoval(SCLoc); |
1441 | 0 | } else { |
1442 | 0 | Keyword = "explicit"; |
1443 | 0 | SCLoc = getExplicitSpecLoc(); |
1444 | 0 | Hint = FixItHint::CreateRemoval(getExplicitSpecRange()); |
1445 | 0 | } |
1446 | |
|
1447 | 0 | S.Diag(SCLoc, diag::err_friend_decl_spec) |
1448 | 0 | << Keyword << Hint; |
1449 | |
|
1450 | 0 | FS_virtual_specified = false; |
1451 | 0 | FS_explicit_specifier = ExplicitSpecifier(); |
1452 | 0 | FS_virtualLoc = FS_explicitLoc = SourceLocation(); |
1453 | 0 | } |
1454 | | |
1455 | 14.8k | assert(!TypeSpecOwned || isDeclRep((TST) TypeSpecType)); |
1456 | | |
1457 | | // Okay, now we can infer the real type. |
1458 | | |
1459 | | // TODO: return "auto function" and other bad things based on the real type. |
1460 | | |
1461 | | // 'data definition has no type or storage class'? |
1462 | 14.8k | } |
1463 | | |
1464 | 8 | bool DeclSpec::isMissingDeclaratorOk() { |
1465 | 8 | TST tst = getTypeSpecType(); |
1466 | 8 | return isDeclRep(tst) && getRepAsDecl() != nullptr && |
1467 | 8 | StorageClassSpec != DeclSpec::SCS_typedef; |
1468 | 8 | } |
1469 | | |
1470 | | void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc, |
1471 | | OverloadedOperatorKind Op, |
1472 | 0 | SourceLocation SymbolLocations[3]) { |
1473 | 0 | Kind = UnqualifiedIdKind::IK_OperatorFunctionId; |
1474 | 0 | StartLocation = OperatorLoc; |
1475 | 0 | EndLocation = OperatorLoc; |
1476 | 0 | new (&OperatorFunctionId) struct OFI; |
1477 | 0 | OperatorFunctionId.Operator = Op; |
1478 | 0 | for (unsigned I = 0; I != 3; ++I) { |
1479 | 0 | OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I]; |
1480 | |
|
1481 | 0 | if (SymbolLocations[I].isValid()) |
1482 | 0 | EndLocation = SymbolLocations[I]; |
1483 | 0 | } |
1484 | 0 | } |
1485 | | |
1486 | | bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc, |
1487 | 0 | const char *&PrevSpec) { |
1488 | 0 | if (!FirstLocation.isValid()) |
1489 | 0 | FirstLocation = Loc; |
1490 | 0 | LastLocation = Loc; |
1491 | 0 | LastSpecifier = VS; |
1492 | |
|
1493 | 0 | if (Specifiers & VS) { |
1494 | 0 | PrevSpec = getSpecifierName(VS); |
1495 | 0 | return true; |
1496 | 0 | } |
1497 | | |
1498 | 0 | Specifiers |= VS; |
1499 | |
|
1500 | 0 | switch (VS) { |
1501 | 0 | default: llvm_unreachable("Unknown specifier!"); |
1502 | 0 | case VS_Override: VS_overrideLoc = Loc; break; |
1503 | 0 | case VS_GNU_Final: |
1504 | 0 | case VS_Sealed: |
1505 | 0 | case VS_Final: VS_finalLoc = Loc; break; |
1506 | 0 | case VS_Abstract: VS_abstractLoc = Loc; break; |
1507 | 0 | } |
1508 | | |
1509 | 0 | return false; |
1510 | 0 | } |
1511 | | |
1512 | 0 | const char *VirtSpecifiers::getSpecifierName(Specifier VS) { |
1513 | 0 | switch (VS) { |
1514 | 0 | default: llvm_unreachable("Unknown specifier"); |
1515 | 0 | case VS_Override: return "override"; |
1516 | 0 | case VS_Final: return "final"; |
1517 | 0 | case VS_GNU_Final: return "__final"; |
1518 | 0 | case VS_Sealed: return "sealed"; |
1519 | 0 | case VS_Abstract: return "abstract"; |
1520 | 0 | } |
1521 | 0 | } |