File: | tools/clang/lib/Sema/SemaExprMember.cpp |
Warning: | line 1009, column 26 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- SemaExprMember.cpp - Semantic Analysis for Expressions -----------===// | ||||
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 member access expressions. | ||||
10 | // | ||||
11 | //===----------------------------------------------------------------------===// | ||||
12 | #include "clang/Sema/Overload.h" | ||||
13 | #include "clang/AST/ASTLambda.h" | ||||
14 | #include "clang/AST/DeclCXX.h" | ||||
15 | #include "clang/AST/DeclObjC.h" | ||||
16 | #include "clang/AST/DeclTemplate.h" | ||||
17 | #include "clang/AST/ExprCXX.h" | ||||
18 | #include "clang/AST/ExprObjC.h" | ||||
19 | #include "clang/Lex/Preprocessor.h" | ||||
20 | #include "clang/Sema/Lookup.h" | ||||
21 | #include "clang/Sema/Scope.h" | ||||
22 | #include "clang/Sema/ScopeInfo.h" | ||||
23 | #include "clang/Sema/SemaInternal.h" | ||||
24 | |||||
25 | using namespace clang; | ||||
26 | using namespace sema; | ||||
27 | |||||
28 | typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> BaseSet; | ||||
29 | |||||
30 | /// Determines if the given class is provably not derived from all of | ||||
31 | /// the prospective base classes. | ||||
32 | static bool isProvablyNotDerivedFrom(Sema &SemaRef, CXXRecordDecl *Record, | ||||
33 | const BaseSet &Bases) { | ||||
34 | auto BaseIsNotInSet = [&Bases](const CXXRecordDecl *Base) { | ||||
35 | return !Bases.count(Base->getCanonicalDecl()); | ||||
36 | }; | ||||
37 | return BaseIsNotInSet(Record) && Record->forallBases(BaseIsNotInSet); | ||||
38 | } | ||||
39 | |||||
40 | enum IMAKind { | ||||
41 | /// The reference is definitely not an instance member access. | ||||
42 | IMA_Static, | ||||
43 | |||||
44 | /// The reference may be an implicit instance member access. | ||||
45 | IMA_Mixed, | ||||
46 | |||||
47 | /// The reference may be to an instance member, but it might be invalid if | ||||
48 | /// so, because the context is not an instance method. | ||||
49 | IMA_Mixed_StaticContext, | ||||
50 | |||||
51 | /// The reference may be to an instance member, but it is invalid if | ||||
52 | /// so, because the context is from an unrelated class. | ||||
53 | IMA_Mixed_Unrelated, | ||||
54 | |||||
55 | /// The reference is definitely an implicit instance member access. | ||||
56 | IMA_Instance, | ||||
57 | |||||
58 | /// The reference may be to an unresolved using declaration. | ||||
59 | IMA_Unresolved, | ||||
60 | |||||
61 | /// The reference is a contextually-permitted abstract member reference. | ||||
62 | IMA_Abstract, | ||||
63 | |||||
64 | /// The reference may be to an unresolved using declaration and the | ||||
65 | /// context is not an instance method. | ||||
66 | IMA_Unresolved_StaticContext, | ||||
67 | |||||
68 | // The reference refers to a field which is not a member of the containing | ||||
69 | // class, which is allowed because we're in C++11 mode and the context is | ||||
70 | // unevaluated. | ||||
71 | IMA_Field_Uneval_Context, | ||||
72 | |||||
73 | /// All possible referrents are instance members and the current | ||||
74 | /// context is not an instance method. | ||||
75 | IMA_Error_StaticContext, | ||||
76 | |||||
77 | /// All possible referrents are instance members of an unrelated | ||||
78 | /// class. | ||||
79 | IMA_Error_Unrelated | ||||
80 | }; | ||||
81 | |||||
82 | /// The given lookup names class member(s) and is not being used for | ||||
83 | /// an address-of-member expression. Classify the type of access | ||||
84 | /// according to whether it's possible that this reference names an | ||||
85 | /// instance member. This is best-effort in dependent contexts; it is okay to | ||||
86 | /// conservatively answer "yes", in which case some errors will simply | ||||
87 | /// not be caught until template-instantiation. | ||||
88 | static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, | ||||
89 | const LookupResult &R) { | ||||
90 | assert(!R.empty() && (*R.begin())->isCXXClassMember())((!R.empty() && (*R.begin())->isCXXClassMember()) ? static_cast<void> (0) : __assert_fail ("!R.empty() && (*R.begin())->isCXXClassMember()" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 90, __PRETTY_FUNCTION__)); | ||||
91 | |||||
92 | DeclContext *DC = SemaRef.getFunctionLevelDeclContext(); | ||||
93 | |||||
94 | bool isStaticContext = SemaRef.CXXThisTypeOverride.isNull() && | ||||
95 | (!isa<CXXMethodDecl>(DC) || cast<CXXMethodDecl>(DC)->isStatic()); | ||||
96 | |||||
97 | if (R.isUnresolvableResult()) | ||||
98 | return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved; | ||||
99 | |||||
100 | // Collect all the declaring classes of instance members we find. | ||||
101 | bool hasNonInstance = false; | ||||
102 | bool isField = false; | ||||
103 | BaseSet Classes; | ||||
104 | for (NamedDecl *D : R) { | ||||
105 | // Look through any using decls. | ||||
106 | D = D->getUnderlyingDecl(); | ||||
107 | |||||
108 | if (D->isCXXInstanceMember()) { | ||||
109 | isField |= isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) || | ||||
110 | isa<IndirectFieldDecl>(D); | ||||
111 | |||||
112 | CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext()); | ||||
113 | Classes.insert(R->getCanonicalDecl()); | ||||
114 | } else | ||||
115 | hasNonInstance = true; | ||||
116 | } | ||||
117 | |||||
118 | // If we didn't find any instance members, it can't be an implicit | ||||
119 | // member reference. | ||||
120 | if (Classes.empty()) | ||||
121 | return IMA_Static; | ||||
122 | |||||
123 | // C++11 [expr.prim.general]p12: | ||||
124 | // An id-expression that denotes a non-static data member or non-static | ||||
125 | // member function of a class can only be used: | ||||
126 | // (...) | ||||
127 | // - if that id-expression denotes a non-static data member and it | ||||
128 | // appears in an unevaluated operand. | ||||
129 | // | ||||
130 | // This rule is specific to C++11. However, we also permit this form | ||||
131 | // in unevaluated inline assembly operands, like the operand to a SIZE. | ||||
132 | IMAKind AbstractInstanceResult = IMA_Static; // happens to be 'false' | ||||
133 | assert(!AbstractInstanceResult)((!AbstractInstanceResult) ? static_cast<void> (0) : __assert_fail ("!AbstractInstanceResult", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 133, __PRETTY_FUNCTION__)); | ||||
134 | switch (SemaRef.ExprEvalContexts.back().Context) { | ||||
135 | case Sema::ExpressionEvaluationContext::Unevaluated: | ||||
136 | case Sema::ExpressionEvaluationContext::UnevaluatedList: | ||||
137 | if (isField && SemaRef.getLangOpts().CPlusPlus11) | ||||
138 | AbstractInstanceResult = IMA_Field_Uneval_Context; | ||||
139 | break; | ||||
140 | |||||
141 | case Sema::ExpressionEvaluationContext::UnevaluatedAbstract: | ||||
142 | AbstractInstanceResult = IMA_Abstract; | ||||
143 | break; | ||||
144 | |||||
145 | case Sema::ExpressionEvaluationContext::DiscardedStatement: | ||||
146 | case Sema::ExpressionEvaluationContext::ConstantEvaluated: | ||||
147 | case Sema::ExpressionEvaluationContext::PotentiallyEvaluated: | ||||
148 | case Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed: | ||||
149 | break; | ||||
150 | } | ||||
151 | |||||
152 | // If the current context is not an instance method, it can't be | ||||
153 | // an implicit member reference. | ||||
154 | if (isStaticContext) { | ||||
155 | if (hasNonInstance) | ||||
156 | return IMA_Mixed_StaticContext; | ||||
157 | |||||
158 | return AbstractInstanceResult ? AbstractInstanceResult | ||||
159 | : IMA_Error_StaticContext; | ||||
160 | } | ||||
161 | |||||
162 | CXXRecordDecl *contextClass; | ||||
163 | if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) | ||||
164 | contextClass = MD->getParent()->getCanonicalDecl(); | ||||
165 | else | ||||
166 | contextClass = cast<CXXRecordDecl>(DC); | ||||
167 | |||||
168 | // [class.mfct.non-static]p3: | ||||
169 | // ...is used in the body of a non-static member function of class X, | ||||
170 | // if name lookup (3.4.1) resolves the name in the id-expression to a | ||||
171 | // non-static non-type member of some class C [...] | ||||
172 | // ...if C is not X or a base class of X, the class member access expression | ||||
173 | // is ill-formed. | ||||
174 | if (R.getNamingClass() && | ||||
175 | contextClass->getCanonicalDecl() != | ||||
176 | R.getNamingClass()->getCanonicalDecl()) { | ||||
177 | // If the naming class is not the current context, this was a qualified | ||||
178 | // member name lookup, and it's sufficient to check that we have the naming | ||||
179 | // class as a base class. | ||||
180 | Classes.clear(); | ||||
181 | Classes.insert(R.getNamingClass()->getCanonicalDecl()); | ||||
182 | } | ||||
183 | |||||
184 | // If we can prove that the current context is unrelated to all the | ||||
185 | // declaring classes, it can't be an implicit member reference (in | ||||
186 | // which case it's an error if any of those members are selected). | ||||
187 | if (isProvablyNotDerivedFrom(SemaRef, contextClass, Classes)) | ||||
188 | return hasNonInstance ? IMA_Mixed_Unrelated : | ||||
189 | AbstractInstanceResult ? AbstractInstanceResult : | ||||
190 | IMA_Error_Unrelated; | ||||
191 | |||||
192 | return (hasNonInstance ? IMA_Mixed : IMA_Instance); | ||||
193 | } | ||||
194 | |||||
195 | /// Diagnose a reference to a field with no object available. | ||||
196 | static void diagnoseInstanceReference(Sema &SemaRef, | ||||
197 | const CXXScopeSpec &SS, | ||||
198 | NamedDecl *Rep, | ||||
199 | const DeclarationNameInfo &nameInfo) { | ||||
200 | SourceLocation Loc = nameInfo.getLoc(); | ||||
201 | SourceRange Range(Loc); | ||||
202 | if (SS.isSet()) Range.setBegin(SS.getRange().getBegin()); | ||||
203 | |||||
204 | // Look through using shadow decls and aliases. | ||||
205 | Rep = Rep->getUnderlyingDecl(); | ||||
206 | |||||
207 | DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext(); | ||||
208 | CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionLevelDC); | ||||
209 | CXXRecordDecl *ContextClass = Method ? Method->getParent() : nullptr; | ||||
210 | CXXRecordDecl *RepClass = dyn_cast<CXXRecordDecl>(Rep->getDeclContext()); | ||||
211 | |||||
212 | bool InStaticMethod = Method && Method->isStatic(); | ||||
213 | bool IsField = isa<FieldDecl>(Rep) || isa<IndirectFieldDecl>(Rep); | ||||
214 | |||||
215 | if (IsField && InStaticMethod) | ||||
216 | // "invalid use of member 'x' in static member function" | ||||
217 | SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method) | ||||
218 | << Range << nameInfo.getName(); | ||||
219 | else if (ContextClass && RepClass && SS.isEmpty() && !InStaticMethod && | ||||
220 | !RepClass->Equals(ContextClass) && RepClass->Encloses(ContextClass)) | ||||
221 | // Unqualified lookup in a non-static member function found a member of an | ||||
222 | // enclosing class. | ||||
223 | SemaRef.Diag(Loc, diag::err_nested_non_static_member_use) | ||||
224 | << IsField << RepClass << nameInfo.getName() << ContextClass << Range; | ||||
225 | else if (IsField) | ||||
226 | SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use) | ||||
227 | << nameInfo.getName() << Range; | ||||
228 | else | ||||
229 | SemaRef.Diag(Loc, diag::err_member_call_without_object) | ||||
230 | << Range; | ||||
231 | } | ||||
232 | |||||
233 | /// Builds an expression which might be an implicit member expression. | ||||
234 | ExprResult | ||||
235 | Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, | ||||
236 | SourceLocation TemplateKWLoc, | ||||
237 | LookupResult &R, | ||||
238 | const TemplateArgumentListInfo *TemplateArgs, | ||||
239 | const Scope *S) { | ||||
240 | switch (ClassifyImplicitMemberAccess(*this, R)) { | ||||
241 | case IMA_Instance: | ||||
242 | return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S); | ||||
243 | |||||
244 | case IMA_Mixed: | ||||
245 | case IMA_Mixed_Unrelated: | ||||
246 | case IMA_Unresolved: | ||||
247 | return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false, | ||||
248 | S); | ||||
249 | |||||
250 | case IMA_Field_Uneval_Context: | ||||
251 | Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use) | ||||
252 | << R.getLookupNameInfo().getName(); | ||||
253 | LLVM_FALLTHROUGH[[gnu::fallthrough]]; | ||||
254 | case IMA_Static: | ||||
255 | case IMA_Abstract: | ||||
256 | case IMA_Mixed_StaticContext: | ||||
257 | case IMA_Unresolved_StaticContext: | ||||
258 | if (TemplateArgs || TemplateKWLoc.isValid()) | ||||
259 | return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs); | ||||
260 | return BuildDeclarationNameExpr(SS, R, false); | ||||
261 | |||||
262 | case IMA_Error_StaticContext: | ||||
263 | case IMA_Error_Unrelated: | ||||
264 | diagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(), | ||||
265 | R.getLookupNameInfo()); | ||||
266 | return ExprError(); | ||||
267 | } | ||||
268 | |||||
269 | llvm_unreachable("unexpected instance member access kind")::llvm::llvm_unreachable_internal("unexpected instance member access kind" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 269); | ||||
270 | } | ||||
271 | |||||
272 | /// Determine whether input char is from rgba component set. | ||||
273 | static bool | ||||
274 | IsRGBA(char c) { | ||||
275 | switch (c) { | ||||
276 | case 'r': | ||||
277 | case 'g': | ||||
278 | case 'b': | ||||
279 | case 'a': | ||||
280 | return true; | ||||
281 | default: | ||||
282 | return false; | ||||
283 | } | ||||
284 | } | ||||
285 | |||||
286 | // OpenCL v1.1, s6.1.7 | ||||
287 | // The component swizzle length must be in accordance with the acceptable | ||||
288 | // vector sizes. | ||||
289 | static bool IsValidOpenCLComponentSwizzleLength(unsigned len) | ||||
290 | { | ||||
291 | return (len >= 1 && len <= 4) || len == 8 || len == 16; | ||||
292 | } | ||||
293 | |||||
294 | /// Check an ext-vector component access expression. | ||||
295 | /// | ||||
296 | /// VK should be set in advance to the value kind of the base | ||||
297 | /// expression. | ||||
298 | static QualType | ||||
299 | CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK, | ||||
300 | SourceLocation OpLoc, const IdentifierInfo *CompName, | ||||
301 | SourceLocation CompLoc) { | ||||
302 | // FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements, | ||||
303 | // see FIXME there. | ||||
304 | // | ||||
305 | // FIXME: This logic can be greatly simplified by splitting it along | ||||
306 | // halving/not halving and reworking the component checking. | ||||
307 | const ExtVectorType *vecType = baseType->getAs<ExtVectorType>(); | ||||
308 | |||||
309 | // The vector accessor can't exceed the number of elements. | ||||
310 | const char *compStr = CompName->getNameStart(); | ||||
311 | |||||
312 | // This flag determines whether or not the component is one of the four | ||||
313 | // special names that indicate a subset of exactly half the elements are | ||||
314 | // to be selected. | ||||
315 | bool HalvingSwizzle = false; | ||||
316 | |||||
317 | // This flag determines whether or not CompName has an 's' char prefix, | ||||
318 | // indicating that it is a string of hex values to be used as vector indices. | ||||
319 | bool HexSwizzle = (*compStr == 's' || *compStr == 'S') && compStr[1]; | ||||
320 | |||||
321 | bool HasRepeated = false; | ||||
322 | bool HasIndex[16] = {}; | ||||
323 | |||||
324 | int Idx; | ||||
325 | |||||
326 | // Check that we've found one of the special components, or that the component | ||||
327 | // names must come from the same set. | ||||
328 | if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") || | ||||
329 | !strcmp(compStr, "even") || !strcmp(compStr, "odd")) { | ||||
330 | HalvingSwizzle = true; | ||||
331 | } else if (!HexSwizzle && | ||||
332 | (Idx = vecType->getPointAccessorIdx(*compStr)) != -1) { | ||||
333 | bool HasRGBA = IsRGBA(*compStr); | ||||
334 | do { | ||||
335 | // Ensure that xyzw and rgba components don't intermingle. | ||||
336 | if (HasRGBA != IsRGBA(*compStr)) | ||||
337 | break; | ||||
338 | if (HasIndex[Idx]) HasRepeated = true; | ||||
339 | HasIndex[Idx] = true; | ||||
340 | compStr++; | ||||
341 | } while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1); | ||||
342 | |||||
343 | // Emit a warning if an rgba selector is used earlier than OpenCL 2.2 | ||||
344 | if (HasRGBA || (*compStr && IsRGBA(*compStr))) { | ||||
345 | if (S.getLangOpts().OpenCL && S.getLangOpts().OpenCLVersion < 220) { | ||||
346 | const char *DiagBegin = HasRGBA ? CompName->getNameStart() : compStr; | ||||
347 | S.Diag(OpLoc, diag::ext_opencl_ext_vector_type_rgba_selector) | ||||
348 | << StringRef(DiagBegin, 1) | ||||
349 | << S.getLangOpts().OpenCLVersion << SourceRange(CompLoc); | ||||
350 | } | ||||
351 | } | ||||
352 | } else { | ||||
353 | if (HexSwizzle) compStr++; | ||||
354 | while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) { | ||||
355 | if (HasIndex[Idx]) HasRepeated = true; | ||||
356 | HasIndex[Idx] = true; | ||||
357 | compStr++; | ||||
358 | } | ||||
359 | } | ||||
360 | |||||
361 | if (!HalvingSwizzle && *compStr) { | ||||
362 | // We didn't get to the end of the string. This means the component names | ||||
363 | // didn't come from the same set *or* we encountered an illegal name. | ||||
364 | S.Diag(OpLoc, diag::err_ext_vector_component_name_illegal) | ||||
365 | << StringRef(compStr, 1) << SourceRange(CompLoc); | ||||
366 | return QualType(); | ||||
367 | } | ||||
368 | |||||
369 | // Ensure no component accessor exceeds the width of the vector type it | ||||
370 | // operates on. | ||||
371 | if (!HalvingSwizzle) { | ||||
372 | compStr = CompName->getNameStart(); | ||||
373 | |||||
374 | if (HexSwizzle) | ||||
375 | compStr++; | ||||
376 | |||||
377 | while (*compStr) { | ||||
378 | if (!vecType->isAccessorWithinNumElements(*compStr++, HexSwizzle)) { | ||||
379 | S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length) | ||||
380 | << baseType << SourceRange(CompLoc); | ||||
381 | return QualType(); | ||||
382 | } | ||||
383 | } | ||||
384 | } | ||||
385 | |||||
386 | // OpenCL mode requires swizzle length to be in accordance with accepted | ||||
387 | // sizes. Clang however supports arbitrary lengths for other languages. | ||||
388 | if (S.getLangOpts().OpenCL && !HalvingSwizzle) { | ||||
389 | unsigned SwizzleLength = CompName->getLength(); | ||||
390 | |||||
391 | if (HexSwizzle) | ||||
392 | SwizzleLength--; | ||||
393 | |||||
394 | if (IsValidOpenCLComponentSwizzleLength(SwizzleLength) == false) { | ||||
395 | S.Diag(OpLoc, diag::err_opencl_ext_vector_component_invalid_length) | ||||
396 | << SwizzleLength << SourceRange(CompLoc); | ||||
397 | return QualType(); | ||||
398 | } | ||||
399 | } | ||||
400 | |||||
401 | // The component accessor looks fine - now we need to compute the actual type. | ||||
402 | // The vector type is implied by the component accessor. For example, | ||||
403 | // vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc. | ||||
404 | // vec4.s0 is a float, vec4.s23 is a vec3, etc. | ||||
405 | // vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2. | ||||
406 | unsigned CompSize = HalvingSwizzle ? (vecType->getNumElements() + 1) / 2 | ||||
407 | : CompName->getLength(); | ||||
408 | if (HexSwizzle) | ||||
409 | CompSize--; | ||||
410 | |||||
411 | if (CompSize == 1) | ||||
412 | return vecType->getElementType(); | ||||
413 | |||||
414 | if (HasRepeated) VK = VK_RValue; | ||||
415 | |||||
416 | QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize); | ||||
417 | // Now look up the TypeDefDecl from the vector type. Without this, | ||||
418 | // diagostics look bad. We want extended vector types to appear built-in. | ||||
419 | for (Sema::ExtVectorDeclsType::iterator | ||||
420 | I = S.ExtVectorDecls.begin(S.getExternalSource()), | ||||
421 | E = S.ExtVectorDecls.end(); | ||||
422 | I != E; ++I) { | ||||
423 | if ((*I)->getUnderlyingType() == VT) | ||||
424 | return S.Context.getTypedefType(*I); | ||||
425 | } | ||||
426 | |||||
427 | return VT; // should never get here (a typedef type should always be found). | ||||
428 | } | ||||
429 | |||||
430 | static Decl *FindGetterSetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl, | ||||
431 | IdentifierInfo *Member, | ||||
432 | const Selector &Sel, | ||||
433 | ASTContext &Context) { | ||||
434 | if (Member) | ||||
435 | if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration( | ||||
436 | Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) | ||||
437 | return PD; | ||||
438 | if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel)) | ||||
439 | return OMD; | ||||
440 | |||||
441 | for (const auto *I : PDecl->protocols()) { | ||||
442 | if (Decl *D = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel, | ||||
443 | Context)) | ||||
444 | return D; | ||||
445 | } | ||||
446 | return nullptr; | ||||
447 | } | ||||
448 | |||||
449 | static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy, | ||||
450 | IdentifierInfo *Member, | ||||
451 | const Selector &Sel, | ||||
452 | ASTContext &Context) { | ||||
453 | // Check protocols on qualified interfaces. | ||||
454 | Decl *GDecl = nullptr; | ||||
455 | for (const auto *I : QIdTy->quals()) { | ||||
456 | if (Member) | ||||
457 | if (ObjCPropertyDecl *PD = I->FindPropertyDeclaration( | ||||
458 | Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { | ||||
459 | GDecl = PD; | ||||
460 | break; | ||||
461 | } | ||||
462 | // Also must look for a getter or setter name which uses property syntax. | ||||
463 | if (ObjCMethodDecl *OMD = I->getInstanceMethod(Sel)) { | ||||
464 | GDecl = OMD; | ||||
465 | break; | ||||
466 | } | ||||
467 | } | ||||
468 | if (!GDecl) { | ||||
469 | for (const auto *I : QIdTy->quals()) { | ||||
470 | // Search in the protocol-qualifier list of current protocol. | ||||
471 | GDecl = FindGetterSetterNameDeclFromProtocolList(I, Member, Sel, Context); | ||||
472 | if (GDecl) | ||||
473 | return GDecl; | ||||
474 | } | ||||
475 | } | ||||
476 | return GDecl; | ||||
477 | } | ||||
478 | |||||
479 | ExprResult | ||||
480 | Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, | ||||
481 | bool IsArrow, SourceLocation OpLoc, | ||||
482 | const CXXScopeSpec &SS, | ||||
483 | SourceLocation TemplateKWLoc, | ||||
484 | NamedDecl *FirstQualifierInScope, | ||||
485 | const DeclarationNameInfo &NameInfo, | ||||
486 | const TemplateArgumentListInfo *TemplateArgs) { | ||||
487 | // Even in dependent contexts, try to diagnose base expressions with | ||||
488 | // obviously wrong types, e.g.: | ||||
489 | // | ||||
490 | // T* t; | ||||
491 | // t.f; | ||||
492 | // | ||||
493 | // In Obj-C++, however, the above expression is valid, since it could be | ||||
494 | // accessing the 'f' property if T is an Obj-C interface. The extra check | ||||
495 | // allows this, while still reporting an error if T is a struct pointer. | ||||
496 | if (!IsArrow) { | ||||
497 | const PointerType *PT = BaseType->getAs<PointerType>(); | ||||
498 | if (PT && (!getLangOpts().ObjC || | ||||
499 | PT->getPointeeType()->isRecordType())) { | ||||
500 | assert(BaseExpr && "cannot happen with implicit member accesses")((BaseExpr && "cannot happen with implicit member accesses" ) ? static_cast<void> (0) : __assert_fail ("BaseExpr && \"cannot happen with implicit member accesses\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 500, __PRETTY_FUNCTION__)); | ||||
501 | Diag(OpLoc, diag::err_typecheck_member_reference_struct_union) | ||||
502 | << BaseType << BaseExpr->getSourceRange() << NameInfo.getSourceRange(); | ||||
503 | return ExprError(); | ||||
504 | } | ||||
505 | } | ||||
506 | |||||
507 | assert(BaseType->isDependentType() ||((BaseType->isDependentType() || NameInfo.getName().isDependentName () || isDependentScopeSpecifier(SS)) ? static_cast<void> (0) : __assert_fail ("BaseType->isDependentType() || NameInfo.getName().isDependentName() || isDependentScopeSpecifier(SS)" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 509, __PRETTY_FUNCTION__)) | ||||
508 | NameInfo.getName().isDependentName() ||((BaseType->isDependentType() || NameInfo.getName().isDependentName () || isDependentScopeSpecifier(SS)) ? static_cast<void> (0) : __assert_fail ("BaseType->isDependentType() || NameInfo.getName().isDependentName() || isDependentScopeSpecifier(SS)" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 509, __PRETTY_FUNCTION__)) | ||||
509 | isDependentScopeSpecifier(SS))((BaseType->isDependentType() || NameInfo.getName().isDependentName () || isDependentScopeSpecifier(SS)) ? static_cast<void> (0) : __assert_fail ("BaseType->isDependentType() || NameInfo.getName().isDependentName() || isDependentScopeSpecifier(SS)" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 509, __PRETTY_FUNCTION__)); | ||||
510 | |||||
511 | // Get the type being accessed in BaseType. If this is an arrow, the BaseExpr | ||||
512 | // must have pointer type, and the accessed type is the pointee. | ||||
513 | return CXXDependentScopeMemberExpr::Create( | ||||
514 | Context, BaseExpr, BaseType, IsArrow, OpLoc, | ||||
515 | SS.getWithLocInContext(Context), TemplateKWLoc, FirstQualifierInScope, | ||||
516 | NameInfo, TemplateArgs); | ||||
517 | } | ||||
518 | |||||
519 | /// We know that the given qualified member reference points only to | ||||
520 | /// declarations which do not belong to the static type of the base | ||||
521 | /// expression. Diagnose the problem. | ||||
522 | static void DiagnoseQualifiedMemberReference(Sema &SemaRef, | ||||
523 | Expr *BaseExpr, | ||||
524 | QualType BaseType, | ||||
525 | const CXXScopeSpec &SS, | ||||
526 | NamedDecl *rep, | ||||
527 | const DeclarationNameInfo &nameInfo) { | ||||
528 | // If this is an implicit member access, use a different set of | ||||
529 | // diagnostics. | ||||
530 | if (!BaseExpr) | ||||
531 | return diagnoseInstanceReference(SemaRef, SS, rep, nameInfo); | ||||
532 | |||||
533 | SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated) | ||||
534 | << SS.getRange() << rep << BaseType; | ||||
535 | } | ||||
536 | |||||
537 | // Check whether the declarations we found through a nested-name | ||||
538 | // specifier in a member expression are actually members of the base | ||||
539 | // type. The restriction here is: | ||||
540 | // | ||||
541 | // C++ [expr.ref]p2: | ||||
542 | // ... In these cases, the id-expression shall name a | ||||
543 | // member of the class or of one of its base classes. | ||||
544 | // | ||||
545 | // So it's perfectly legitimate for the nested-name specifier to name | ||||
546 | // an unrelated class, and for us to find an overload set including | ||||
547 | // decls from classes which are not superclasses, as long as the decl | ||||
548 | // we actually pick through overload resolution is from a superclass. | ||||
549 | bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, | ||||
550 | QualType BaseType, | ||||
551 | const CXXScopeSpec &SS, | ||||
552 | const LookupResult &R) { | ||||
553 | CXXRecordDecl *BaseRecord = | ||||
554 | cast_or_null<CXXRecordDecl>(computeDeclContext(BaseType)); | ||||
555 | if (!BaseRecord) { | ||||
556 | // We can't check this yet because the base type is still | ||||
557 | // dependent. | ||||
558 | assert(BaseType->isDependentType())((BaseType->isDependentType()) ? static_cast<void> ( 0) : __assert_fail ("BaseType->isDependentType()", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 558, __PRETTY_FUNCTION__)); | ||||
559 | return false; | ||||
560 | } | ||||
561 | |||||
562 | for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { | ||||
563 | // If this is an implicit member reference and we find a | ||||
564 | // non-instance member, it's not an error. | ||||
565 | if (!BaseExpr && !(*I)->isCXXInstanceMember()) | ||||
566 | return false; | ||||
567 | |||||
568 | // Note that we use the DC of the decl, not the underlying decl. | ||||
569 | DeclContext *DC = (*I)->getDeclContext(); | ||||
570 | while (DC->isTransparentContext()) | ||||
571 | DC = DC->getParent(); | ||||
572 | |||||
573 | if (!DC->isRecord()) | ||||
574 | continue; | ||||
575 | |||||
576 | CXXRecordDecl *MemberRecord = cast<CXXRecordDecl>(DC)->getCanonicalDecl(); | ||||
577 | if (BaseRecord->getCanonicalDecl() == MemberRecord || | ||||
578 | !BaseRecord->isProvablyNotDerivedFrom(MemberRecord)) | ||||
579 | return false; | ||||
580 | } | ||||
581 | |||||
582 | DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, SS, | ||||
583 | R.getRepresentativeDecl(), | ||||
584 | R.getLookupNameInfo()); | ||||
585 | return true; | ||||
586 | } | ||||
587 | |||||
588 | namespace { | ||||
589 | |||||
590 | // Callback to only accept typo corrections that are either a ValueDecl or a | ||||
591 | // FunctionTemplateDecl and are declared in the current record or, for a C++ | ||||
592 | // classes, one of its base classes. | ||||
593 | class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback { | ||||
594 | public: | ||||
595 | explicit RecordMemberExprValidatorCCC(const RecordType *RTy) | ||||
596 | : Record(RTy->getDecl()) { | ||||
597 | // Don't add bare keywords to the consumer since they will always fail | ||||
598 | // validation by virtue of not being associated with any decls. | ||||
599 | WantTypeSpecifiers = false; | ||||
600 | WantExpressionKeywords = false; | ||||
601 | WantCXXNamedCasts = false; | ||||
602 | WantFunctionLikeCasts = false; | ||||
603 | WantRemainingKeywords = false; | ||||
604 | } | ||||
605 | |||||
606 | bool ValidateCandidate(const TypoCorrection &candidate) override { | ||||
607 | NamedDecl *ND = candidate.getCorrectionDecl(); | ||||
608 | // Don't accept candidates that cannot be member functions, constants, | ||||
609 | // variables, or templates. | ||||
610 | if (!ND || !(isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND))) | ||||
611 | return false; | ||||
612 | |||||
613 | // Accept candidates that occur in the current record. | ||||
614 | if (Record->containsDecl(ND)) | ||||
615 | return true; | ||||
616 | |||||
617 | if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Record)) { | ||||
618 | // Accept candidates that occur in any of the current class' base classes. | ||||
619 | for (const auto &BS : RD->bases()) { | ||||
620 | if (const RecordType *BSTy = | ||||
621 | dyn_cast_or_null<RecordType>(BS.getType().getTypePtrOrNull())) { | ||||
622 | if (BSTy->getDecl()->containsDecl(ND)) | ||||
623 | return true; | ||||
624 | } | ||||
625 | } | ||||
626 | } | ||||
627 | |||||
628 | return false; | ||||
629 | } | ||||
630 | |||||
631 | std::unique_ptr<CorrectionCandidateCallback> clone() override { | ||||
632 | return std::make_unique<RecordMemberExprValidatorCCC>(*this); | ||||
633 | } | ||||
634 | |||||
635 | private: | ||||
636 | const RecordDecl *const Record; | ||||
637 | }; | ||||
638 | |||||
639 | } | ||||
640 | |||||
641 | static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, | ||||
642 | Expr *BaseExpr, | ||||
643 | const RecordType *RTy, | ||||
644 | SourceLocation OpLoc, bool IsArrow, | ||||
645 | CXXScopeSpec &SS, bool HasTemplateArgs, | ||||
646 | SourceLocation TemplateKWLoc, | ||||
647 | TypoExpr *&TE) { | ||||
648 | SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange(); | ||||
649 | RecordDecl *RDecl = RTy->getDecl(); | ||||
650 | if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) && | ||||
651 | SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0), | ||||
652 | diag::err_typecheck_incomplete_tag, | ||||
653 | BaseRange)) | ||||
654 | return true; | ||||
655 | |||||
656 | if (HasTemplateArgs || TemplateKWLoc.isValid()) { | ||||
657 | // LookupTemplateName doesn't expect these both to exist simultaneously. | ||||
658 | QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0); | ||||
659 | |||||
660 | bool MOUS; | ||||
661 | return SemaRef.LookupTemplateName(R, nullptr, SS, ObjectType, false, MOUS, | ||||
662 | TemplateKWLoc); | ||||
663 | } | ||||
664 | |||||
665 | DeclContext *DC = RDecl; | ||||
666 | if (SS.isSet()) { | ||||
667 | // If the member name was a qualified-id, look into the | ||||
668 | // nested-name-specifier. | ||||
669 | DC = SemaRef.computeDeclContext(SS, false); | ||||
670 | |||||
671 | if (SemaRef.RequireCompleteDeclContext(SS, DC)) { | ||||
672 | SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag) | ||||
673 | << SS.getRange() << DC; | ||||
674 | return true; | ||||
675 | } | ||||
676 | |||||
677 | assert(DC && "Cannot handle non-computable dependent contexts in lookup")((DC && "Cannot handle non-computable dependent contexts in lookup" ) ? static_cast<void> (0) : __assert_fail ("DC && \"Cannot handle non-computable dependent contexts in lookup\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 677, __PRETTY_FUNCTION__)); | ||||
678 | |||||
679 | if (!isa<TypeDecl>(DC)) { | ||||
680 | SemaRef.Diag(R.getNameLoc(), diag::err_qualified_member_nonclass) | ||||
681 | << DC << SS.getRange(); | ||||
682 | return true; | ||||
683 | } | ||||
684 | } | ||||
685 | |||||
686 | // The record definition is complete, now look up the member. | ||||
687 | SemaRef.LookupQualifiedName(R, DC, SS); | ||||
688 | |||||
689 | if (!R.empty()) | ||||
690 | return false; | ||||
691 | |||||
692 | DeclarationName Typo = R.getLookupName(); | ||||
693 | SourceLocation TypoLoc = R.getNameLoc(); | ||||
694 | |||||
695 | struct QueryState { | ||||
696 | Sema &SemaRef; | ||||
697 | DeclarationNameInfo NameInfo; | ||||
698 | Sema::LookupNameKind LookupKind; | ||||
699 | Sema::RedeclarationKind Redecl; | ||||
700 | }; | ||||
701 | QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(), | ||||
702 | R.redeclarationKind()}; | ||||
703 | RecordMemberExprValidatorCCC CCC(RTy); | ||||
704 | TE = SemaRef.CorrectTypoDelayed( | ||||
705 | R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS, CCC, | ||||
706 | [=, &SemaRef](const TypoCorrection &TC) { | ||||
707 | if (TC) { | ||||
708 | assert(!TC.isKeyword() &&((!TC.isKeyword() && "Got a keyword as a correction for a member!" ) ? static_cast<void> (0) : __assert_fail ("!TC.isKeyword() && \"Got a keyword as a correction for a member!\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 709, __PRETTY_FUNCTION__)) | ||||
709 | "Got a keyword as a correction for a member!")((!TC.isKeyword() && "Got a keyword as a correction for a member!" ) ? static_cast<void> (0) : __assert_fail ("!TC.isKeyword() && \"Got a keyword as a correction for a member!\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 709, __PRETTY_FUNCTION__)); | ||||
710 | bool DroppedSpecifier = | ||||
711 | TC.WillReplaceSpecifier() && | ||||
712 | Typo.getAsString() == TC.getAsString(SemaRef.getLangOpts()); | ||||
713 | SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest) | ||||
714 | << Typo << DC << DroppedSpecifier | ||||
715 | << SS.getRange()); | ||||
716 | } else { | ||||
717 | SemaRef.Diag(TypoLoc, diag::err_no_member) << Typo << DC << BaseRange; | ||||
718 | } | ||||
719 | }, | ||||
720 | [=](Sema &SemaRef, TypoExpr *TE, TypoCorrection TC) mutable { | ||||
721 | LookupResult R(Q.SemaRef, Q.NameInfo, Q.LookupKind, Q.Redecl); | ||||
722 | R.clear(); // Ensure there's no decls lingering in the shared state. | ||||
723 | R.suppressDiagnostics(); | ||||
724 | R.setLookupName(TC.getCorrection()); | ||||
725 | for (NamedDecl *ND : TC) | ||||
726 | R.addDecl(ND); | ||||
727 | R.resolveKind(); | ||||
728 | return SemaRef.BuildMemberReferenceExpr( | ||||
729 | BaseExpr, BaseExpr->getType(), OpLoc, IsArrow, SS, SourceLocation(), | ||||
730 | nullptr, R, nullptr, nullptr); | ||||
731 | }, | ||||
732 | Sema::CTK_ErrorRecovery, DC); | ||||
733 | |||||
734 | return false; | ||||
735 | } | ||||
736 | |||||
737 | static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, | ||||
738 | ExprResult &BaseExpr, bool &IsArrow, | ||||
739 | SourceLocation OpLoc, CXXScopeSpec &SS, | ||||
740 | Decl *ObjCImpDecl, bool HasTemplateArgs, | ||||
741 | SourceLocation TemplateKWLoc); | ||||
742 | |||||
743 | ExprResult | ||||
744 | Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, | ||||
745 | SourceLocation OpLoc, bool IsArrow, | ||||
746 | CXXScopeSpec &SS, | ||||
747 | SourceLocation TemplateKWLoc, | ||||
748 | NamedDecl *FirstQualifierInScope, | ||||
749 | const DeclarationNameInfo &NameInfo, | ||||
750 | const TemplateArgumentListInfo *TemplateArgs, | ||||
751 | const Scope *S, | ||||
752 | ActOnMemberAccessExtraArgs *ExtraArgs) { | ||||
753 | if (BaseType->isDependentType() || | ||||
754 | (SS.isSet() && isDependentScopeSpecifier(SS))) | ||||
755 | return ActOnDependentMemberExpr(Base, BaseType, | ||||
756 | IsArrow, OpLoc, | ||||
757 | SS, TemplateKWLoc, FirstQualifierInScope, | ||||
758 | NameInfo, TemplateArgs); | ||||
759 | |||||
760 | LookupResult R(*this, NameInfo, LookupMemberName); | ||||
761 | |||||
762 | // Implicit member accesses. | ||||
763 | if (!Base) { | ||||
764 | TypoExpr *TE = nullptr; | ||||
765 | QualType RecordTy = BaseType; | ||||
766 | if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType(); | ||||
767 | if (LookupMemberExprInRecord( | ||||
768 | *this, R, nullptr, RecordTy->getAs<RecordType>(), OpLoc, IsArrow, | ||||
769 | SS, TemplateArgs != nullptr, TemplateKWLoc, TE)) | ||||
770 | return ExprError(); | ||||
771 | if (TE) | ||||
772 | return TE; | ||||
773 | |||||
774 | // Explicit member accesses. | ||||
775 | } else { | ||||
776 | ExprResult BaseResult = Base; | ||||
777 | ExprResult Result = | ||||
778 | LookupMemberExpr(*this, R, BaseResult, IsArrow, OpLoc, SS, | ||||
779 | ExtraArgs ? ExtraArgs->ObjCImpDecl : nullptr, | ||||
780 | TemplateArgs != nullptr, TemplateKWLoc); | ||||
781 | |||||
782 | if (BaseResult.isInvalid()) | ||||
783 | return ExprError(); | ||||
784 | Base = BaseResult.get(); | ||||
785 | |||||
786 | if (Result.isInvalid()) | ||||
787 | return ExprError(); | ||||
788 | |||||
789 | if (Result.get()) | ||||
790 | return Result; | ||||
791 | |||||
792 | // LookupMemberExpr can modify Base, and thus change BaseType | ||||
793 | BaseType = Base->getType(); | ||||
794 | } | ||||
795 | |||||
796 | return BuildMemberReferenceExpr(Base, BaseType, | ||||
797 | OpLoc, IsArrow, SS, TemplateKWLoc, | ||||
798 | FirstQualifierInScope, R, TemplateArgs, S, | ||||
799 | false, ExtraArgs); | ||||
800 | } | ||||
801 | |||||
802 | ExprResult | ||||
803 | Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, | ||||
804 | SourceLocation loc, | ||||
805 | IndirectFieldDecl *indirectField, | ||||
806 | DeclAccessPair foundDecl, | ||||
807 | Expr *baseObjectExpr, | ||||
808 | SourceLocation opLoc) { | ||||
809 | // First, build the expression that refers to the base object. | ||||
810 | |||||
811 | // Case 1: the base of the indirect field is not a field. | ||||
812 | VarDecl *baseVariable = indirectField->getVarDecl(); | ||||
813 | CXXScopeSpec EmptySS; | ||||
814 | if (baseVariable) { | ||||
815 | assert(baseVariable->getType()->isRecordType())((baseVariable->getType()->isRecordType()) ? static_cast <void> (0) : __assert_fail ("baseVariable->getType()->isRecordType()" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 815, __PRETTY_FUNCTION__)); | ||||
816 | |||||
817 | // In principle we could have a member access expression that | ||||
818 | // accesses an anonymous struct/union that's a static member of | ||||
819 | // the base object's class. However, under the current standard, | ||||
820 | // static data members cannot be anonymous structs or unions. | ||||
821 | // Supporting this is as easy as building a MemberExpr here. | ||||
822 | assert(!baseObjectExpr && "anonymous struct/union is static data member?")((!baseObjectExpr && "anonymous struct/union is static data member?" ) ? static_cast<void> (0) : __assert_fail ("!baseObjectExpr && \"anonymous struct/union is static data member?\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 822, __PRETTY_FUNCTION__)); | ||||
823 | |||||
824 | DeclarationNameInfo baseNameInfo(DeclarationName(), loc); | ||||
825 | |||||
826 | ExprResult result | ||||
827 | = BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable); | ||||
828 | if (result.isInvalid()) return ExprError(); | ||||
829 | |||||
830 | baseObjectExpr = result.get(); | ||||
831 | } | ||||
832 | |||||
833 | assert((baseVariable || baseObjectExpr) &&(((baseVariable || baseObjectExpr) && "referencing anonymous struct/union without a base variable or " "expression") ? static_cast<void> (0) : __assert_fail ( "(baseVariable || baseObjectExpr) && \"referencing anonymous struct/union without a base variable or \" \"expression\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 835, __PRETTY_FUNCTION__)) | ||||
834 | "referencing anonymous struct/union without a base variable or "(((baseVariable || baseObjectExpr) && "referencing anonymous struct/union without a base variable or " "expression") ? static_cast<void> (0) : __assert_fail ( "(baseVariable || baseObjectExpr) && \"referencing anonymous struct/union without a base variable or \" \"expression\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 835, __PRETTY_FUNCTION__)) | ||||
835 | "expression")(((baseVariable || baseObjectExpr) && "referencing anonymous struct/union without a base variable or " "expression") ? static_cast<void> (0) : __assert_fail ( "(baseVariable || baseObjectExpr) && \"referencing anonymous struct/union without a base variable or \" \"expression\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 835, __PRETTY_FUNCTION__)); | ||||
836 | |||||
837 | // Build the implicit member references to the field of the | ||||
838 | // anonymous struct/union. | ||||
839 | Expr *result = baseObjectExpr; | ||||
840 | IndirectFieldDecl::chain_iterator | ||||
841 | FI = indirectField->chain_begin(), FEnd = indirectField->chain_end(); | ||||
842 | |||||
843 | // Case 2: the base of the indirect field is a field and the user | ||||
844 | // wrote a member expression. | ||||
845 | if (!baseVariable) { | ||||
846 | FieldDecl *field = cast<FieldDecl>(*FI); | ||||
847 | |||||
848 | bool baseObjectIsPointer = baseObjectExpr->getType()->isPointerType(); | ||||
849 | |||||
850 | // Make a nameInfo that properly uses the anonymous name. | ||||
851 | DeclarationNameInfo memberNameInfo(field->getDeclName(), loc); | ||||
852 | |||||
853 | // Build the first member access in the chain with full information. | ||||
854 | result = | ||||
855 | BuildFieldReferenceExpr(result, baseObjectIsPointer, SourceLocation(), | ||||
856 | SS, field, foundDecl, memberNameInfo) | ||||
857 | .get(); | ||||
858 | if (!result) | ||||
859 | return ExprError(); | ||||
860 | } | ||||
861 | |||||
862 | // In all cases, we should now skip the first declaration in the chain. | ||||
863 | ++FI; | ||||
864 | |||||
865 | while (FI != FEnd) { | ||||
866 | FieldDecl *field = cast<FieldDecl>(*FI++); | ||||
867 | |||||
868 | // FIXME: these are somewhat meaningless | ||||
869 | DeclarationNameInfo memberNameInfo(field->getDeclName(), loc); | ||||
870 | DeclAccessPair fakeFoundDecl = | ||||
871 | DeclAccessPair::make(field, field->getAccess()); | ||||
872 | |||||
873 | result = | ||||
874 | BuildFieldReferenceExpr(result, /*isarrow*/ false, SourceLocation(), | ||||
875 | (FI == FEnd ? SS : EmptySS), field, | ||||
876 | fakeFoundDecl, memberNameInfo) | ||||
877 | .get(); | ||||
878 | } | ||||
879 | |||||
880 | return result; | ||||
881 | } | ||||
882 | |||||
883 | static ExprResult | ||||
884 | BuildMSPropertyRefExpr(Sema &S, Expr *BaseExpr, bool IsArrow, | ||||
885 | const CXXScopeSpec &SS, | ||||
886 | MSPropertyDecl *PD, | ||||
887 | const DeclarationNameInfo &NameInfo) { | ||||
888 | // Property names are always simple identifiers and therefore never | ||||
889 | // require any interesting additional storage. | ||||
890 | return new (S.Context) MSPropertyRefExpr(BaseExpr, PD, IsArrow, | ||||
891 | S.Context.PseudoObjectTy, VK_LValue, | ||||
892 | SS.getWithLocInContext(S.Context), | ||||
893 | NameInfo.getLoc()); | ||||
894 | } | ||||
895 | |||||
896 | MemberExpr *Sema::BuildMemberExpr( | ||||
897 | Expr *Base, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec *SS, | ||||
898 | SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, | ||||
899 | bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, | ||||
900 | QualType Ty, ExprValueKind VK, ExprObjectKind OK, | ||||
901 | const TemplateArgumentListInfo *TemplateArgs) { | ||||
902 | NestedNameSpecifierLoc NNS = | ||||
903 | SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(); | ||||
904 | return BuildMemberExpr(Base, IsArrow, OpLoc, NNS, TemplateKWLoc, Member, | ||||
905 | FoundDecl, HadMultipleCandidates, MemberNameInfo, Ty, | ||||
906 | VK, OK, TemplateArgs); | ||||
907 | } | ||||
908 | |||||
909 | MemberExpr *Sema::BuildMemberExpr( | ||||
910 | Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS, | ||||
911 | SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, | ||||
912 | bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, | ||||
913 | QualType Ty, ExprValueKind VK, ExprObjectKind OK, | ||||
914 | const TemplateArgumentListInfo *TemplateArgs) { | ||||
915 | assert((!IsArrow || Base->isRValue()) && "-> base must be a pointer rvalue")(((!IsArrow || Base->isRValue()) && "-> base must be a pointer rvalue" ) ? static_cast<void> (0) : __assert_fail ("(!IsArrow || Base->isRValue()) && \"-> base must be a pointer rvalue\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 915, __PRETTY_FUNCTION__)); | ||||
916 | MemberExpr *E = | ||||
917 | MemberExpr::Create(Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc, | ||||
918 | Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty, | ||||
919 | VK, OK, getNonOdrUseReasonInCurrentContext(Member)); | ||||
920 | E->setHadMultipleCandidates(HadMultipleCandidates); | ||||
921 | MarkMemberReferenced(E); | ||||
922 | return E; | ||||
923 | } | ||||
924 | |||||
925 | /// Determine if the given scope is within a function-try-block handler. | ||||
926 | static bool IsInFnTryBlockHandler(const Scope *S) { | ||||
927 | // Walk the scope stack until finding a FnTryCatchScope, or leave the | ||||
928 | // function scope. If a FnTryCatchScope is found, check whether the TryScope | ||||
929 | // flag is set. If it is not, it's a function-try-block handler. | ||||
930 | for (; S != S->getFnParent(); S = S->getParent()) { | ||||
931 | if (S->getFlags() & Scope::FnTryCatchScope) | ||||
932 | return (S->getFlags() & Scope::TryScope) != Scope::TryScope; | ||||
933 | } | ||||
934 | return false; | ||||
935 | } | ||||
936 | |||||
937 | VarDecl * | ||||
938 | Sema::getVarTemplateSpecialization(VarTemplateDecl *VarTempl, | ||||
939 | const TemplateArgumentListInfo *TemplateArgs, | ||||
940 | const DeclarationNameInfo &MemberNameInfo, | ||||
941 | SourceLocation TemplateKWLoc) { | ||||
942 | if (!TemplateArgs) { | ||||
943 | diagnoseMissingTemplateArguments(TemplateName(VarTempl), | ||||
944 | MemberNameInfo.getBeginLoc()); | ||||
945 | return nullptr; | ||||
946 | } | ||||
947 | |||||
948 | DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc, | ||||
949 | MemberNameInfo.getLoc(), *TemplateArgs); | ||||
950 | if (VDecl.isInvalid()) | ||||
951 | return nullptr; | ||||
952 | VarDecl *Var = cast<VarDecl>(VDecl.get()); | ||||
953 | if (!Var->getTemplateSpecializationKind()) | ||||
954 | Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation, | ||||
955 | MemberNameInfo.getLoc()); | ||||
956 | return Var; | ||||
957 | } | ||||
958 | |||||
959 | ExprResult | ||||
960 | Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, | ||||
961 | SourceLocation OpLoc, bool IsArrow, | ||||
962 | const CXXScopeSpec &SS, | ||||
963 | SourceLocation TemplateKWLoc, | ||||
964 | NamedDecl *FirstQualifierInScope, | ||||
965 | LookupResult &R, | ||||
966 | const TemplateArgumentListInfo *TemplateArgs, | ||||
967 | const Scope *S, | ||||
968 | bool SuppressQualifierCheck, | ||||
969 | ActOnMemberAccessExtraArgs *ExtraArgs) { | ||||
970 | QualType BaseType = BaseExprType; | ||||
971 | if (IsArrow) { | ||||
| |||||
972 | assert(BaseType->isPointerType())((BaseType->isPointerType()) ? static_cast<void> (0) : __assert_fail ("BaseType->isPointerType()", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 972, __PRETTY_FUNCTION__)); | ||||
973 | BaseType = BaseType->castAs<PointerType>()->getPointeeType(); | ||||
974 | } | ||||
975 | R.setBaseObjectType(BaseType); | ||||
976 | |||||
977 | // C++1z [expr.ref]p2: | ||||
978 | // For the first option (dot) the first expression shall be a glvalue [...] | ||||
979 | if (!IsArrow
| ||||
980 | ExprResult Converted = TemporaryMaterializationConversion(BaseExpr); | ||||
981 | if (Converted.isInvalid()) | ||||
982 | return ExprError(); | ||||
983 | BaseExpr = Converted.get(); | ||||
984 | } | ||||
985 | |||||
986 | |||||
987 | const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo(); | ||||
988 | DeclarationName MemberName = MemberNameInfo.getName(); | ||||
989 | SourceLocation MemberLoc = MemberNameInfo.getLoc(); | ||||
990 | |||||
991 | if (R.isAmbiguous()) | ||||
992 | return ExprError(); | ||||
993 | |||||
994 | // [except.handle]p10: Referring to any non-static member or base class of an | ||||
995 | // object in the handler for a function-try-block of a constructor or | ||||
996 | // destructor for that object results in undefined behavior. | ||||
997 | const auto *FD = getCurFunctionDecl(); | ||||
998 | if (S && BaseExpr && FD && | ||||
999 | (isa<CXXDestructorDecl>(FD) || isa<CXXConstructorDecl>(FD)) && | ||||
1000 | isa<CXXThisExpr>(BaseExpr->IgnoreImpCasts()) && | ||||
1001 | IsInFnTryBlockHandler(S)) | ||||
1002 | Diag(MemberLoc, diag::warn_cdtor_function_try_handler_mem_expr) | ||||
1003 | << isa<CXXDestructorDecl>(FD); | ||||
1004 | |||||
1005 | if (R.empty()) { | ||||
1006 | // Rederive where we looked up. | ||||
1007 | DeclContext *DC = (SS.isSet() | ||||
1008 | ? computeDeclContext(SS, false) | ||||
1009 | : BaseType->getAs<RecordType>()->getDecl()); | ||||
| |||||
1010 | |||||
1011 | if (ExtraArgs) { | ||||
1012 | ExprResult RetryExpr; | ||||
1013 | if (!IsArrow && BaseExpr) { | ||||
1014 | SFINAETrap Trap(*this, true); | ||||
1015 | ParsedType ObjectType; | ||||
1016 | bool MayBePseudoDestructor = false; | ||||
1017 | RetryExpr = ActOnStartCXXMemberReference(getCurScope(), BaseExpr, | ||||
1018 | OpLoc, tok::arrow, ObjectType, | ||||
1019 | MayBePseudoDestructor); | ||||
1020 | if (RetryExpr.isUsable() && !Trap.hasErrorOccurred()) { | ||||
1021 | CXXScopeSpec TempSS(SS); | ||||
1022 | RetryExpr = ActOnMemberAccessExpr( | ||||
1023 | ExtraArgs->S, RetryExpr.get(), OpLoc, tok::arrow, TempSS, | ||||
1024 | TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl); | ||||
1025 | } | ||||
1026 | if (Trap.hasErrorOccurred()) | ||||
1027 | RetryExpr = ExprError(); | ||||
1028 | } | ||||
1029 | if (RetryExpr.isUsable()) { | ||||
1030 | Diag(OpLoc, diag::err_no_member_overloaded_arrow) | ||||
1031 | << MemberName << DC << FixItHint::CreateReplacement(OpLoc, "->"); | ||||
1032 | return RetryExpr; | ||||
1033 | } | ||||
1034 | } | ||||
1035 | |||||
1036 | Diag(R.getNameLoc(), diag::err_no_member) | ||||
1037 | << MemberName << DC | ||||
1038 | << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); | ||||
1039 | return ExprError(); | ||||
1040 | } | ||||
1041 | |||||
1042 | // Diagnose lookups that find only declarations from a non-base | ||||
1043 | // type. This is possible for either qualified lookups (which may | ||||
1044 | // have been qualified with an unrelated type) or implicit member | ||||
1045 | // expressions (which were found with unqualified lookup and thus | ||||
1046 | // may have come from an enclosing scope). Note that it's okay for | ||||
1047 | // lookup to find declarations from a non-base type as long as those | ||||
1048 | // aren't the ones picked by overload resolution. | ||||
1049 | if ((SS.isSet() || !BaseExpr || | ||||
1050 | (isa<CXXThisExpr>(BaseExpr) && | ||||
1051 | cast<CXXThisExpr>(BaseExpr)->isImplicit())) && | ||||
1052 | !SuppressQualifierCheck && | ||||
1053 | CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R)) | ||||
1054 | return ExprError(); | ||||
1055 | |||||
1056 | // Construct an unresolved result if we in fact got an unresolved | ||||
1057 | // result. | ||||
1058 | if (R.isOverloadedResult() || R.isUnresolvableResult()) { | ||||
1059 | // Suppress any lookup-related diagnostics; we'll do these when we | ||||
1060 | // pick a member. | ||||
1061 | R.suppressDiagnostics(); | ||||
1062 | |||||
1063 | UnresolvedMemberExpr *MemExpr | ||||
1064 | = UnresolvedMemberExpr::Create(Context, R.isUnresolvableResult(), | ||||
1065 | BaseExpr, BaseExprType, | ||||
1066 | IsArrow, OpLoc, | ||||
1067 | SS.getWithLocInContext(Context), | ||||
1068 | TemplateKWLoc, MemberNameInfo, | ||||
1069 | TemplateArgs, R.begin(), R.end()); | ||||
1070 | |||||
1071 | return MemExpr; | ||||
1072 | } | ||||
1073 | |||||
1074 | assert(R.isSingleResult())((R.isSingleResult()) ? static_cast<void> (0) : __assert_fail ("R.isSingleResult()", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 1074, __PRETTY_FUNCTION__)); | ||||
1075 | DeclAccessPair FoundDecl = R.begin().getPair(); | ||||
1076 | NamedDecl *MemberDecl = R.getFoundDecl(); | ||||
1077 | |||||
1078 | // FIXME: diagnose the presence of template arguments now. | ||||
1079 | |||||
1080 | // If the decl being referenced had an error, return an error for this | ||||
1081 | // sub-expr without emitting another error, in order to avoid cascading | ||||
1082 | // error cases. | ||||
1083 | if (MemberDecl->isInvalidDecl()) | ||||
1084 | return ExprError(); | ||||
1085 | |||||
1086 | // Handle the implicit-member-access case. | ||||
1087 | if (!BaseExpr) { | ||||
1088 | // If this is not an instance member, convert to a non-member access. | ||||
1089 | if (!MemberDecl->isCXXInstanceMember()) { | ||||
1090 | // If this is a variable template, get the instantiated variable | ||||
1091 | // declaration corresponding to the supplied template arguments | ||||
1092 | // (while emitting diagnostics as necessary) that will be referenced | ||||
1093 | // by this expression. | ||||
1094 | assert((!TemplateArgs || isa<VarTemplateDecl>(MemberDecl)) &&(((!TemplateArgs || isa<VarTemplateDecl>(MemberDecl)) && "How did we get template arguments here sans a variable template" ) ? static_cast<void> (0) : __assert_fail ("(!TemplateArgs || isa<VarTemplateDecl>(MemberDecl)) && \"How did we get template arguments here sans a variable template\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 1095, __PRETTY_FUNCTION__)) | ||||
1095 | "How did we get template arguments here sans a variable template")(((!TemplateArgs || isa<VarTemplateDecl>(MemberDecl)) && "How did we get template arguments here sans a variable template" ) ? static_cast<void> (0) : __assert_fail ("(!TemplateArgs || isa<VarTemplateDecl>(MemberDecl)) && \"How did we get template arguments here sans a variable template\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 1095, __PRETTY_FUNCTION__)); | ||||
1096 | if (isa<VarTemplateDecl>(MemberDecl)) { | ||||
1097 | MemberDecl = getVarTemplateSpecialization( | ||||
1098 | cast<VarTemplateDecl>(MemberDecl), TemplateArgs, | ||||
1099 | R.getLookupNameInfo(), TemplateKWLoc); | ||||
1100 | if (!MemberDecl) | ||||
1101 | return ExprError(); | ||||
1102 | } | ||||
1103 | return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl, | ||||
1104 | FoundDecl, TemplateArgs); | ||||
1105 | } | ||||
1106 | SourceLocation Loc = R.getNameLoc(); | ||||
1107 | if (SS.getRange().isValid()) | ||||
1108 | Loc = SS.getRange().getBegin(); | ||||
1109 | BaseExpr = BuildCXXThisExpr(Loc, BaseExprType, /*IsImplicit=*/true); | ||||
1110 | } | ||||
1111 | |||||
1112 | // Check the use of this member. | ||||
1113 | if (DiagnoseUseOfDecl(MemberDecl, MemberLoc)) | ||||
1114 | return ExprError(); | ||||
1115 | |||||
1116 | if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) | ||||
1117 | return BuildFieldReferenceExpr(BaseExpr, IsArrow, OpLoc, SS, FD, FoundDecl, | ||||
1118 | MemberNameInfo); | ||||
1119 | |||||
1120 | if (MSPropertyDecl *PD = dyn_cast<MSPropertyDecl>(MemberDecl)) | ||||
1121 | return BuildMSPropertyRefExpr(*this, BaseExpr, IsArrow, SS, PD, | ||||
1122 | MemberNameInfo); | ||||
1123 | |||||
1124 | if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl)) | ||||
1125 | // We may have found a field within an anonymous union or struct | ||||
1126 | // (C++ [class.union]). | ||||
1127 | return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD, | ||||
1128 | FoundDecl, BaseExpr, | ||||
1129 | OpLoc); | ||||
1130 | |||||
1131 | if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { | ||||
1132 | return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, | ||||
1133 | FoundDecl, /*HadMultipleCandidates=*/false, | ||||
1134 | MemberNameInfo, Var->getType().getNonReferenceType(), | ||||
1135 | VK_LValue, OK_Ordinary); | ||||
1136 | } | ||||
1137 | |||||
1138 | if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) { | ||||
1139 | ExprValueKind valueKind; | ||||
1140 | QualType type; | ||||
1141 | if (MemberFn->isInstance()) { | ||||
1142 | valueKind = VK_RValue; | ||||
1143 | type = Context.BoundMemberTy; | ||||
1144 | } else { | ||||
1145 | valueKind = VK_LValue; | ||||
1146 | type = MemberFn->getType(); | ||||
1147 | } | ||||
1148 | |||||
1149 | return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, | ||||
1150 | MemberFn, FoundDecl, /*HadMultipleCandidates=*/false, | ||||
1151 | MemberNameInfo, type, valueKind, OK_Ordinary); | ||||
1152 | } | ||||
1153 | assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?")((!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?" ) ? static_cast<void> (0) : __assert_fail ("!isa<FunctionDecl>(MemberDecl) && \"member function not C++ method?\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 1153, __PRETTY_FUNCTION__)); | ||||
1154 | |||||
1155 | if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) { | ||||
1156 | return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Enum, | ||||
1157 | FoundDecl, /*HadMultipleCandidates=*/false, | ||||
1158 | MemberNameInfo, Enum->getType(), VK_RValue, | ||||
1159 | OK_Ordinary); | ||||
1160 | } | ||||
1161 | if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) { | ||||
1162 | if (VarDecl *Var = getVarTemplateSpecialization( | ||||
1163 | VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc)) | ||||
1164 | return BuildMemberExpr( | ||||
1165 | BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, FoundDecl, | ||||
1166 | /*HadMultipleCandidates=*/false, MemberNameInfo, | ||||
1167 | Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary); | ||||
1168 | return ExprError(); | ||||
1169 | } | ||||
1170 | |||||
1171 | // We found something that we didn't expect. Complain. | ||||
1172 | if (isa<TypeDecl>(MemberDecl)) | ||||
1173 | Diag(MemberLoc, diag::err_typecheck_member_reference_type) | ||||
1174 | << MemberName << BaseType << int(IsArrow); | ||||
1175 | else | ||||
1176 | Diag(MemberLoc, diag::err_typecheck_member_reference_unknown) | ||||
1177 | << MemberName << BaseType << int(IsArrow); | ||||
1178 | |||||
1179 | Diag(MemberDecl->getLocation(), diag::note_member_declared_here) | ||||
1180 | << MemberName; | ||||
1181 | R.suppressDiagnostics(); | ||||
1182 | return ExprError(); | ||||
1183 | } | ||||
1184 | |||||
1185 | /// Given that normal member access failed on the given expression, | ||||
1186 | /// and given that the expression's type involves builtin-id or | ||||
1187 | /// builtin-Class, decide whether substituting in the redefinition | ||||
1188 | /// types would be profitable. The redefinition type is whatever | ||||
1189 | /// this translation unit tried to typedef to id/Class; we store | ||||
1190 | /// it to the side and then re-use it in places like this. | ||||
1191 | static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) { | ||||
1192 | const ObjCObjectPointerType *opty | ||||
1193 | = base.get()->getType()->getAs<ObjCObjectPointerType>(); | ||||
1194 | if (!opty) return false; | ||||
1195 | |||||
1196 | const ObjCObjectType *ty = opty->getObjectType(); | ||||
1197 | |||||
1198 | QualType redef; | ||||
1199 | if (ty->isObjCId()) { | ||||
1200 | redef = S.Context.getObjCIdRedefinitionType(); | ||||
1201 | } else if (ty->isObjCClass()) { | ||||
1202 | redef = S.Context.getObjCClassRedefinitionType(); | ||||
1203 | } else { | ||||
1204 | return false; | ||||
1205 | } | ||||
1206 | |||||
1207 | // Do the substitution as long as the redefinition type isn't just a | ||||
1208 | // possibly-qualified pointer to builtin-id or builtin-Class again. | ||||
1209 | opty = redef->getAs<ObjCObjectPointerType>(); | ||||
1210 | if (opty && !opty->getObjectType()->getInterface()) | ||||
1211 | return false; | ||||
1212 | |||||
1213 | base = S.ImpCastExprToType(base.get(), redef, CK_BitCast); | ||||
1214 | return true; | ||||
1215 | } | ||||
1216 | |||||
1217 | static bool isRecordType(QualType T) { | ||||
1218 | return T->isRecordType(); | ||||
1219 | } | ||||
1220 | static bool isPointerToRecordType(QualType T) { | ||||
1221 | if (const PointerType *PT = T->getAs<PointerType>()) | ||||
1222 | return PT->getPointeeType()->isRecordType(); | ||||
1223 | return false; | ||||
1224 | } | ||||
1225 | |||||
1226 | /// Perform conversions on the LHS of a member access expression. | ||||
1227 | ExprResult | ||||
1228 | Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) { | ||||
1229 | if (IsArrow && !Base->getType()->isFunctionType()) | ||||
1230 | return DefaultFunctionArrayLvalueConversion(Base); | ||||
1231 | |||||
1232 | return CheckPlaceholderExpr(Base); | ||||
1233 | } | ||||
1234 | |||||
1235 | /// Look up the given member of the given non-type-dependent | ||||
1236 | /// expression. This can return in one of two ways: | ||||
1237 | /// * If it returns a sentinel null-but-valid result, the caller will | ||||
1238 | /// assume that lookup was performed and the results written into | ||||
1239 | /// the provided structure. It will take over from there. | ||||
1240 | /// * Otherwise, the returned expression will be produced in place of | ||||
1241 | /// an ordinary member expression. | ||||
1242 | /// | ||||
1243 | /// The ObjCImpDecl bit is a gross hack that will need to be properly | ||||
1244 | /// fixed for ObjC++. | ||||
1245 | static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, | ||||
1246 | ExprResult &BaseExpr, bool &IsArrow, | ||||
1247 | SourceLocation OpLoc, CXXScopeSpec &SS, | ||||
1248 | Decl *ObjCImpDecl, bool HasTemplateArgs, | ||||
1249 | SourceLocation TemplateKWLoc) { | ||||
1250 | assert(BaseExpr.get() && "no base expression")((BaseExpr.get() && "no base expression") ? static_cast <void> (0) : __assert_fail ("BaseExpr.get() && \"no base expression\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 1250, __PRETTY_FUNCTION__)); | ||||
1251 | |||||
1252 | // Perform default conversions. | ||||
1253 | BaseExpr = S.PerformMemberExprBaseConversion(BaseExpr.get(), IsArrow); | ||||
1254 | if (BaseExpr.isInvalid()) | ||||
1255 | return ExprError(); | ||||
1256 | |||||
1257 | QualType BaseType = BaseExpr.get()->getType(); | ||||
1258 | assert(!BaseType->isDependentType())((!BaseType->isDependentType()) ? static_cast<void> ( 0) : __assert_fail ("!BaseType->isDependentType()", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 1258, __PRETTY_FUNCTION__)); | ||||
1259 | |||||
1260 | DeclarationName MemberName = R.getLookupName(); | ||||
1261 | SourceLocation MemberLoc = R.getNameLoc(); | ||||
1262 | |||||
1263 | // For later type-checking purposes, turn arrow accesses into dot | ||||
1264 | // accesses. The only access type we support that doesn't follow | ||||
1265 | // the C equivalence "a->b === (*a).b" is ObjC property accesses, | ||||
1266 | // and those never use arrows, so this is unaffected. | ||||
1267 | if (IsArrow) { | ||||
1268 | if (const PointerType *Ptr = BaseType->getAs<PointerType>()) | ||||
1269 | BaseType = Ptr->getPointeeType(); | ||||
1270 | else if (const ObjCObjectPointerType *Ptr | ||||
1271 | = BaseType->getAs<ObjCObjectPointerType>()) | ||||
1272 | BaseType = Ptr->getPointeeType(); | ||||
1273 | else if (BaseType->isRecordType()) { | ||||
1274 | // Recover from arrow accesses to records, e.g.: | ||||
1275 | // struct MyRecord foo; | ||||
1276 | // foo->bar | ||||
1277 | // This is actually well-formed in C++ if MyRecord has an | ||||
1278 | // overloaded operator->, but that should have been dealt with | ||||
1279 | // by now--or a diagnostic message already issued if a problem | ||||
1280 | // was encountered while looking for the overloaded operator->. | ||||
1281 | if (!S.getLangOpts().CPlusPlus) { | ||||
1282 | S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) | ||||
1283 | << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() | ||||
1284 | << FixItHint::CreateReplacement(OpLoc, "."); | ||||
1285 | } | ||||
1286 | IsArrow = false; | ||||
1287 | } else if (BaseType->isFunctionType()) { | ||||
1288 | goto fail; | ||||
1289 | } else { | ||||
1290 | S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) | ||||
1291 | << BaseType << BaseExpr.get()->getSourceRange(); | ||||
1292 | return ExprError(); | ||||
1293 | } | ||||
1294 | } | ||||
1295 | |||||
1296 | // Handle field access to simple records. | ||||
1297 | if (const RecordType *RTy = BaseType->getAs<RecordType>()) { | ||||
1298 | TypoExpr *TE = nullptr; | ||||
1299 | if (LookupMemberExprInRecord(S, R, BaseExpr.get(), RTy, OpLoc, IsArrow, SS, | ||||
1300 | HasTemplateArgs, TemplateKWLoc, TE)) | ||||
1301 | return ExprError(); | ||||
1302 | |||||
1303 | // Returning valid-but-null is how we indicate to the caller that | ||||
1304 | // the lookup result was filled in. If typo correction was attempted and | ||||
1305 | // failed, the lookup result will have been cleared--that combined with the | ||||
1306 | // valid-but-null ExprResult will trigger the appropriate diagnostics. | ||||
1307 | return ExprResult(TE); | ||||
1308 | } | ||||
1309 | |||||
1310 | // Handle ivar access to Objective-C objects. | ||||
1311 | if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>()) { | ||||
1312 | if (!SS.isEmpty() && !SS.isInvalid()) { | ||||
1313 | S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access) | ||||
1314 | << 1 << SS.getScopeRep() | ||||
1315 | << FixItHint::CreateRemoval(SS.getRange()); | ||||
1316 | SS.clear(); | ||||
1317 | } | ||||
1318 | |||||
1319 | IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); | ||||
1320 | |||||
1321 | // There are three cases for the base type: | ||||
1322 | // - builtin id (qualified or unqualified) | ||||
1323 | // - builtin Class (qualified or unqualified) | ||||
1324 | // - an interface | ||||
1325 | ObjCInterfaceDecl *IDecl = OTy->getInterface(); | ||||
1326 | if (!IDecl) { | ||||
1327 | if (S.getLangOpts().ObjCAutoRefCount && | ||||
1328 | (OTy->isObjCId() || OTy->isObjCClass())) | ||||
1329 | goto fail; | ||||
1330 | // There's an implicit 'isa' ivar on all objects. | ||||
1331 | // But we only actually find it this way on objects of type 'id', | ||||
1332 | // apparently. | ||||
1333 | if (OTy->isObjCId() && Member->isStr("isa")) | ||||
1334 | return new (S.Context) ObjCIsaExpr(BaseExpr.get(), IsArrow, MemberLoc, | ||||
1335 | OpLoc, S.Context.getObjCClassType()); | ||||
1336 | if (ShouldTryAgainWithRedefinitionType(S, BaseExpr)) | ||||
1337 | return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, | ||||
1338 | ObjCImpDecl, HasTemplateArgs, TemplateKWLoc); | ||||
1339 | goto fail; | ||||
1340 | } | ||||
1341 | |||||
1342 | if (S.RequireCompleteType(OpLoc, BaseType, | ||||
1343 | diag::err_typecheck_incomplete_tag, | ||||
1344 | BaseExpr.get())) | ||||
1345 | return ExprError(); | ||||
1346 | |||||
1347 | ObjCInterfaceDecl *ClassDeclared = nullptr; | ||||
1348 | ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared); | ||||
1349 | |||||
1350 | if (!IV) { | ||||
1351 | // Attempt to correct for typos in ivar names. | ||||
1352 | DeclFilterCCC<ObjCIvarDecl> Validator{}; | ||||
1353 | Validator.IsObjCIvarLookup = IsArrow; | ||||
1354 | if (TypoCorrection Corrected = S.CorrectTypo( | ||||
1355 | R.getLookupNameInfo(), Sema::LookupMemberName, nullptr, nullptr, | ||||
1356 | Validator, Sema::CTK_ErrorRecovery, IDecl)) { | ||||
1357 | IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>(); | ||||
1358 | S.diagnoseTypo( | ||||
1359 | Corrected, | ||||
1360 | S.PDiag(diag::err_typecheck_member_reference_ivar_suggest) | ||||
1361 | << IDecl->getDeclName() << MemberName); | ||||
1362 | |||||
1363 | // Figure out the class that declares the ivar. | ||||
1364 | assert(!ClassDeclared)((!ClassDeclared) ? static_cast<void> (0) : __assert_fail ("!ClassDeclared", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 1364, __PRETTY_FUNCTION__)); | ||||
1365 | |||||
1366 | Decl *D = cast<Decl>(IV->getDeclContext()); | ||||
1367 | if (auto *Category = dyn_cast<ObjCCategoryDecl>(D)) | ||||
1368 | D = Category->getClassInterface(); | ||||
1369 | |||||
1370 | if (auto *Implementation = dyn_cast<ObjCImplementationDecl>(D)) | ||||
1371 | ClassDeclared = Implementation->getClassInterface(); | ||||
1372 | else if (auto *Interface = dyn_cast<ObjCInterfaceDecl>(D)) | ||||
1373 | ClassDeclared = Interface; | ||||
1374 | |||||
1375 | assert(ClassDeclared && "cannot query interface")((ClassDeclared && "cannot query interface") ? static_cast <void> (0) : __assert_fail ("ClassDeclared && \"cannot query interface\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 1375, __PRETTY_FUNCTION__)); | ||||
1376 | } else { | ||||
1377 | if (IsArrow && | ||||
1378 | IDecl->FindPropertyDeclaration( | ||||
1379 | Member, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { | ||||
1380 | S.Diag(MemberLoc, diag::err_property_found_suggest) | ||||
1381 | << Member << BaseExpr.get()->getType() | ||||
1382 | << FixItHint::CreateReplacement(OpLoc, "."); | ||||
1383 | return ExprError(); | ||||
1384 | } | ||||
1385 | |||||
1386 | S.Diag(MemberLoc, diag::err_typecheck_member_reference_ivar) | ||||
1387 | << IDecl->getDeclName() << MemberName | ||||
1388 | << BaseExpr.get()->getSourceRange(); | ||||
1389 | return ExprError(); | ||||
1390 | } | ||||
1391 | } | ||||
1392 | |||||
1393 | assert(ClassDeclared)((ClassDeclared) ? static_cast<void> (0) : __assert_fail ("ClassDeclared", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 1393, __PRETTY_FUNCTION__)); | ||||
1394 | |||||
1395 | // If the decl being referenced had an error, return an error for this | ||||
1396 | // sub-expr without emitting another error, in order to avoid cascading | ||||
1397 | // error cases. | ||||
1398 | if (IV->isInvalidDecl()) | ||||
1399 | return ExprError(); | ||||
1400 | |||||
1401 | // Check whether we can reference this field. | ||||
1402 | if (S.DiagnoseUseOfDecl(IV, MemberLoc)) | ||||
1403 | return ExprError(); | ||||
1404 | if (IV->getAccessControl() != ObjCIvarDecl::Public && | ||||
1405 | IV->getAccessControl() != ObjCIvarDecl::Package) { | ||||
1406 | ObjCInterfaceDecl *ClassOfMethodDecl = nullptr; | ||||
1407 | if (ObjCMethodDecl *MD = S.getCurMethodDecl()) | ||||
1408 | ClassOfMethodDecl = MD->getClassInterface(); | ||||
1409 | else if (ObjCImpDecl && S.getCurFunctionDecl()) { | ||||
1410 | // Case of a c-function declared inside an objc implementation. | ||||
1411 | // FIXME: For a c-style function nested inside an objc implementation | ||||
1412 | // class, there is no implementation context available, so we pass | ||||
1413 | // down the context as argument to this routine. Ideally, this context | ||||
1414 | // need be passed down in the AST node and somehow calculated from the | ||||
1415 | // AST for a function decl. | ||||
1416 | if (ObjCImplementationDecl *IMPD = | ||||
1417 | dyn_cast<ObjCImplementationDecl>(ObjCImpDecl)) | ||||
1418 | ClassOfMethodDecl = IMPD->getClassInterface(); | ||||
1419 | else if (ObjCCategoryImplDecl* CatImplClass = | ||||
1420 | dyn_cast<ObjCCategoryImplDecl>(ObjCImpDecl)) | ||||
1421 | ClassOfMethodDecl = CatImplClass->getClassInterface(); | ||||
1422 | } | ||||
1423 | if (!S.getLangOpts().DebuggerSupport) { | ||||
1424 | if (IV->getAccessControl() == ObjCIvarDecl::Private) { | ||||
1425 | if (!declaresSameEntity(ClassDeclared, IDecl) || | ||||
1426 | !declaresSameEntity(ClassOfMethodDecl, ClassDeclared)) | ||||
1427 | S.Diag(MemberLoc, diag::err_private_ivar_access) | ||||
1428 | << IV->getDeclName(); | ||||
1429 | } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl)) | ||||
1430 | // @protected | ||||
1431 | S.Diag(MemberLoc, diag::err_protected_ivar_access) | ||||
1432 | << IV->getDeclName(); | ||||
1433 | } | ||||
1434 | } | ||||
1435 | bool warn = true; | ||||
1436 | if (S.getLangOpts().ObjCWeak) { | ||||
1437 | Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts(); | ||||
1438 | if (UnaryOperator *UO = dyn_cast<UnaryOperator>(BaseExp)) | ||||
1439 | if (UO->getOpcode() == UO_Deref) | ||||
1440 | BaseExp = UO->getSubExpr()->IgnoreParenCasts(); | ||||
1441 | |||||
1442 | if (DeclRefExpr *DE = dyn_cast<DeclRefExpr>(BaseExp)) | ||||
1443 | if (DE->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { | ||||
1444 | S.Diag(DE->getLocation(), diag::err_arc_weak_ivar_access); | ||||
1445 | warn = false; | ||||
1446 | } | ||||
1447 | } | ||||
1448 | if (warn) { | ||||
1449 | if (ObjCMethodDecl *MD = S.getCurMethodDecl()) { | ||||
1450 | ObjCMethodFamily MF = MD->getMethodFamily(); | ||||
1451 | warn = (MF != OMF_init && MF != OMF_dealloc && | ||||
1452 | MF != OMF_finalize && | ||||
1453 | !S.IvarBacksCurrentMethodAccessor(IDecl, MD, IV)); | ||||
1454 | } | ||||
1455 | if (warn) | ||||
1456 | S.Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName(); | ||||
1457 | } | ||||
1458 | |||||
1459 | ObjCIvarRefExpr *Result = new (S.Context) ObjCIvarRefExpr( | ||||
1460 | IV, IV->getUsageType(BaseType), MemberLoc, OpLoc, BaseExpr.get(), | ||||
1461 | IsArrow); | ||||
1462 | |||||
1463 | if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { | ||||
1464 | if (!S.isUnevaluatedContext() && | ||||
1465 | !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc)) | ||||
1466 | S.getCurFunction()->recordUseOfWeak(Result); | ||||
1467 | } | ||||
1468 | |||||
1469 | return Result; | ||||
1470 | } | ||||
1471 | |||||
1472 | // Objective-C property access. | ||||
1473 | const ObjCObjectPointerType *OPT; | ||||
1474 | if (!IsArrow && (OPT = BaseType->getAs<ObjCObjectPointerType>())) { | ||||
1475 | if (!SS.isEmpty() && !SS.isInvalid()) { | ||||
1476 | S.Diag(SS.getRange().getBegin(), diag::err_qualified_objc_access) | ||||
1477 | << 0 << SS.getScopeRep() << FixItHint::CreateRemoval(SS.getRange()); | ||||
1478 | SS.clear(); | ||||
1479 | } | ||||
1480 | |||||
1481 | // This actually uses the base as an r-value. | ||||
1482 | BaseExpr = S.DefaultLvalueConversion(BaseExpr.get()); | ||||
1483 | if (BaseExpr.isInvalid()) | ||||
1484 | return ExprError(); | ||||
1485 | |||||
1486 | assert(S.Context.hasSameUnqualifiedType(BaseType,((S.Context.hasSameUnqualifiedType(BaseType, BaseExpr.get()-> getType())) ? static_cast<void> (0) : __assert_fail ("S.Context.hasSameUnqualifiedType(BaseType, BaseExpr.get()->getType())" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 1487, __PRETTY_FUNCTION__)) | ||||
1487 | BaseExpr.get()->getType()))((S.Context.hasSameUnqualifiedType(BaseType, BaseExpr.get()-> getType())) ? static_cast<void> (0) : __assert_fail ("S.Context.hasSameUnqualifiedType(BaseType, BaseExpr.get()->getType())" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 1487, __PRETTY_FUNCTION__)); | ||||
1488 | |||||
1489 | IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); | ||||
1490 | |||||
1491 | const ObjCObjectType *OT = OPT->getObjectType(); | ||||
1492 | |||||
1493 | // id, with and without qualifiers. | ||||
1494 | if (OT->isObjCId()) { | ||||
1495 | // Check protocols on qualified interfaces. | ||||
1496 | Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member); | ||||
1497 | if (Decl *PMDecl = | ||||
1498 | FindGetterSetterNameDecl(OPT, Member, Sel, S.Context)) { | ||||
1499 | if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) { | ||||
1500 | // Check the use of this declaration | ||||
1501 | if (S.DiagnoseUseOfDecl(PD, MemberLoc)) | ||||
1502 | return ExprError(); | ||||
1503 | |||||
1504 | return new (S.Context) | ||||
1505 | ObjCPropertyRefExpr(PD, S.Context.PseudoObjectTy, VK_LValue, | ||||
1506 | OK_ObjCProperty, MemberLoc, BaseExpr.get()); | ||||
1507 | } | ||||
1508 | |||||
1509 | if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) { | ||||
1510 | Selector SetterSel = | ||||
1511 | SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(), | ||||
1512 | S.PP.getSelectorTable(), | ||||
1513 | Member); | ||||
1514 | ObjCMethodDecl *SMD = nullptr; | ||||
1515 | if (Decl *SDecl = FindGetterSetterNameDecl(OPT, | ||||
1516 | /*Property id*/ nullptr, | ||||
1517 | SetterSel, S.Context)) | ||||
1518 | SMD = dyn_cast<ObjCMethodDecl>(SDecl); | ||||
1519 | |||||
1520 | return new (S.Context) | ||||
1521 | ObjCPropertyRefExpr(OMD, SMD, S.Context.PseudoObjectTy, VK_LValue, | ||||
1522 | OK_ObjCProperty, MemberLoc, BaseExpr.get()); | ||||
1523 | } | ||||
1524 | } | ||||
1525 | // Use of id.member can only be for a property reference. Do not | ||||
1526 | // use the 'id' redefinition in this case. | ||||
1527 | if (IsArrow && ShouldTryAgainWithRedefinitionType(S, BaseExpr)) | ||||
1528 | return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, | ||||
1529 | ObjCImpDecl, HasTemplateArgs, TemplateKWLoc); | ||||
1530 | |||||
1531 | return ExprError(S.Diag(MemberLoc, diag::err_property_not_found) | ||||
1532 | << MemberName << BaseType); | ||||
1533 | } | ||||
1534 | |||||
1535 | // 'Class', unqualified only. | ||||
1536 | if (OT->isObjCClass()) { | ||||
1537 | // Only works in a method declaration (??!). | ||||
1538 | ObjCMethodDecl *MD = S.getCurMethodDecl(); | ||||
1539 | if (!MD) { | ||||
1540 | if (ShouldTryAgainWithRedefinitionType(S, BaseExpr)) | ||||
1541 | return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, | ||||
1542 | ObjCImpDecl, HasTemplateArgs, TemplateKWLoc); | ||||
1543 | |||||
1544 | goto fail; | ||||
1545 | } | ||||
1546 | |||||
1547 | // Also must look for a getter name which uses property syntax. | ||||
1548 | Selector Sel = S.PP.getSelectorTable().getNullarySelector(Member); | ||||
1549 | ObjCInterfaceDecl *IFace = MD->getClassInterface(); | ||||
1550 | if (!IFace) | ||||
1551 | goto fail; | ||||
1552 | |||||
1553 | ObjCMethodDecl *Getter; | ||||
1554 | if ((Getter = IFace->lookupClassMethod(Sel))) { | ||||
1555 | // Check the use of this method. | ||||
1556 | if (S.DiagnoseUseOfDecl(Getter, MemberLoc)) | ||||
1557 | return ExprError(); | ||||
1558 | } else | ||||
1559 | Getter = IFace->lookupPrivateMethod(Sel, false); | ||||
1560 | // If we found a getter then this may be a valid dot-reference, we | ||||
1561 | // will look for the matching setter, in case it is needed. | ||||
1562 | Selector SetterSel = | ||||
1563 | SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(), | ||||
1564 | S.PP.getSelectorTable(), | ||||
1565 | Member); | ||||
1566 | ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); | ||||
1567 | if (!Setter) { | ||||
1568 | // If this reference is in an @implementation, also check for 'private' | ||||
1569 | // methods. | ||||
1570 | Setter = IFace->lookupPrivateMethod(SetterSel, false); | ||||
1571 | } | ||||
1572 | |||||
1573 | if (Setter && S.DiagnoseUseOfDecl(Setter, MemberLoc)) | ||||
1574 | return ExprError(); | ||||
1575 | |||||
1576 | if (Getter || Setter) { | ||||
1577 | return new (S.Context) ObjCPropertyRefExpr( | ||||
1578 | Getter, Setter, S.Context.PseudoObjectTy, VK_LValue, | ||||
1579 | OK_ObjCProperty, MemberLoc, BaseExpr.get()); | ||||
1580 | } | ||||
1581 | |||||
1582 | if (ShouldTryAgainWithRedefinitionType(S, BaseExpr)) | ||||
1583 | return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, | ||||
1584 | ObjCImpDecl, HasTemplateArgs, TemplateKWLoc); | ||||
1585 | |||||
1586 | return ExprError(S.Diag(MemberLoc, diag::err_property_not_found) | ||||
1587 | << MemberName << BaseType); | ||||
1588 | } | ||||
1589 | |||||
1590 | // Normal property access. | ||||
1591 | return S.HandleExprPropertyRefExpr(OPT, BaseExpr.get(), OpLoc, MemberName, | ||||
1592 | MemberLoc, SourceLocation(), QualType(), | ||||
1593 | false); | ||||
1594 | } | ||||
1595 | |||||
1596 | // Handle 'field access' to vectors, such as 'V.xx'. | ||||
1597 | if (BaseType->isExtVectorType()) { | ||||
1598 | // FIXME: this expr should store IsArrow. | ||||
1599 | IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); | ||||
1600 | ExprValueKind VK; | ||||
1601 | if (IsArrow) | ||||
1602 | VK = VK_LValue; | ||||
1603 | else { | ||||
1604 | if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(BaseExpr.get())) | ||||
1605 | VK = POE->getSyntacticForm()->getValueKind(); | ||||
1606 | else | ||||
1607 | VK = BaseExpr.get()->getValueKind(); | ||||
1608 | } | ||||
1609 | |||||
1610 | QualType ret = CheckExtVectorComponent(S, BaseType, VK, OpLoc, | ||||
1611 | Member, MemberLoc); | ||||
1612 | if (ret.isNull()) | ||||
1613 | return ExprError(); | ||||
1614 | Qualifiers BaseQ = | ||||
1615 | S.Context.getCanonicalType(BaseExpr.get()->getType()).getQualifiers(); | ||||
1616 | ret = S.Context.getQualifiedType(ret, BaseQ); | ||||
1617 | |||||
1618 | return new (S.Context) | ||||
1619 | ExtVectorElementExpr(ret, VK, BaseExpr.get(), *Member, MemberLoc); | ||||
1620 | } | ||||
1621 | |||||
1622 | // Adjust builtin-sel to the appropriate redefinition type if that's | ||||
1623 | // not just a pointer to builtin-sel again. | ||||
1624 | if (IsArrow && BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) && | ||||
1625 | !S.Context.getObjCSelRedefinitionType()->isObjCSelType()) { | ||||
1626 | BaseExpr = S.ImpCastExprToType( | ||||
1627 | BaseExpr.get(), S.Context.getObjCSelRedefinitionType(), CK_BitCast); | ||||
1628 | return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, | ||||
1629 | ObjCImpDecl, HasTemplateArgs, TemplateKWLoc); | ||||
1630 | } | ||||
1631 | |||||
1632 | // Failure cases. | ||||
1633 | fail: | ||||
1634 | |||||
1635 | // Recover from dot accesses to pointers, e.g.: | ||||
1636 | // type *foo; | ||||
1637 | // foo.bar | ||||
1638 | // This is actually well-formed in two cases: | ||||
1639 | // - 'type' is an Objective C type | ||||
1640 | // - 'bar' is a pseudo-destructor name which happens to refer to | ||||
1641 | // the appropriate pointer type | ||||
1642 | if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { | ||||
1643 | if (!IsArrow && Ptr->getPointeeType()->isRecordType() && | ||||
1644 | MemberName.getNameKind() != DeclarationName::CXXDestructorName) { | ||||
1645 | S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) | ||||
1646 | << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() | ||||
1647 | << FixItHint::CreateReplacement(OpLoc, "->"); | ||||
1648 | |||||
1649 | // Recurse as an -> access. | ||||
1650 | IsArrow = true; | ||||
1651 | return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, | ||||
1652 | ObjCImpDecl, HasTemplateArgs, TemplateKWLoc); | ||||
1653 | } | ||||
1654 | } | ||||
1655 | |||||
1656 | // If the user is trying to apply -> or . to a function name, it's probably | ||||
1657 | // because they forgot parentheses to call that function. | ||||
1658 | if (S.tryToRecoverWithCall( | ||||
1659 | BaseExpr, S.PDiag(diag::err_member_reference_needs_call), | ||||
1660 | /*complain*/ false, | ||||
1661 | IsArrow ? &isPointerToRecordType : &isRecordType)) { | ||||
1662 | if (BaseExpr.isInvalid()) | ||||
1663 | return ExprError(); | ||||
1664 | BaseExpr = S.DefaultFunctionArrayConversion(BaseExpr.get()); | ||||
1665 | return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS, | ||||
1666 | ObjCImpDecl, HasTemplateArgs, TemplateKWLoc); | ||||
1667 | } | ||||
1668 | |||||
1669 | S.Diag(OpLoc, diag::err_typecheck_member_reference_struct_union) | ||||
1670 | << BaseType << BaseExpr.get()->getSourceRange() << MemberLoc; | ||||
1671 | |||||
1672 | return ExprError(); | ||||
1673 | } | ||||
1674 | |||||
1675 | /// The main callback when the parser finds something like | ||||
1676 | /// expression . [nested-name-specifier] identifier | ||||
1677 | /// expression -> [nested-name-specifier] identifier | ||||
1678 | /// where 'identifier' encompasses a fairly broad spectrum of | ||||
1679 | /// possibilities, including destructor and operator references. | ||||
1680 | /// | ||||
1681 | /// \param OpKind either tok::arrow or tok::period | ||||
1682 | /// \param ObjCImpDecl the current Objective-C \@implementation | ||||
1683 | /// decl; this is an ugly hack around the fact that Objective-C | ||||
1684 | /// \@implementations aren't properly put in the context chain | ||||
1685 | ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, | ||||
1686 | SourceLocation OpLoc, | ||||
1687 | tok::TokenKind OpKind, | ||||
1688 | CXXScopeSpec &SS, | ||||
1689 | SourceLocation TemplateKWLoc, | ||||
1690 | UnqualifiedId &Id, | ||||
1691 | Decl *ObjCImpDecl) { | ||||
1692 | if (SS.isSet() && SS.isInvalid()) | ||||
1693 | return ExprError(); | ||||
1694 | |||||
1695 | // Warn about the explicit constructor calls Microsoft extension. | ||||
1696 | if (getLangOpts().MicrosoftExt && | ||||
1697 | Id.getKind() == UnqualifiedIdKind::IK_ConstructorName) | ||||
1698 | Diag(Id.getSourceRange().getBegin(), | ||||
1699 | diag::ext_ms_explicit_constructor_call); | ||||
1700 | |||||
1701 | TemplateArgumentListInfo TemplateArgsBuffer; | ||||
1702 | |||||
1703 | // Decompose the name into its component parts. | ||||
1704 | DeclarationNameInfo NameInfo; | ||||
1705 | const TemplateArgumentListInfo *TemplateArgs; | ||||
1706 | DecomposeUnqualifiedId(Id, TemplateArgsBuffer, | ||||
1707 | NameInfo, TemplateArgs); | ||||
1708 | |||||
1709 | DeclarationName Name = NameInfo.getName(); | ||||
1710 | bool IsArrow = (OpKind == tok::arrow); | ||||
1711 | |||||
1712 | NamedDecl *FirstQualifierInScope | ||||
1713 | = (!SS.isSet() ? nullptr : FindFirstQualifierInScope(S, SS.getScopeRep())); | ||||
1714 | |||||
1715 | // This is a postfix expression, so get rid of ParenListExprs. | ||||
1716 | ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base); | ||||
1717 | if (Result.isInvalid()) return ExprError(); | ||||
1718 | Base = Result.get(); | ||||
1719 | |||||
1720 | if (Base->getType()->isDependentType() || Name.isDependentName() || | ||||
1721 | isDependentScopeSpecifier(SS)) { | ||||
1722 | return ActOnDependentMemberExpr(Base, Base->getType(), IsArrow, OpLoc, SS, | ||||
1723 | TemplateKWLoc, FirstQualifierInScope, | ||||
1724 | NameInfo, TemplateArgs); | ||||
1725 | } | ||||
1726 | |||||
1727 | ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl}; | ||||
1728 | ExprResult Res = BuildMemberReferenceExpr( | ||||
1729 | Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc, | ||||
1730 | FirstQualifierInScope, NameInfo, TemplateArgs, S, &ExtraArgs); | ||||
1731 | |||||
1732 | if (!Res.isInvalid() && isa<MemberExpr>(Res.get())) | ||||
1733 | CheckMemberAccessOfNoDeref(cast<MemberExpr>(Res.get())); | ||||
1734 | |||||
1735 | return Res; | ||||
1736 | } | ||||
1737 | |||||
1738 | void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) { | ||||
1739 | QualType ResultTy = E->getType(); | ||||
1740 | |||||
1741 | // Do not warn on member accesses to arrays since this returns an array | ||||
1742 | // lvalue and does not actually dereference memory. | ||||
1743 | if (isa<ArrayType>(ResultTy)) | ||||
1744 | return; | ||||
1745 | |||||
1746 | if (E->isArrow()) { | ||||
1747 | if (const auto *Ptr = dyn_cast<PointerType>( | ||||
1748 | E->getBase()->getType().getDesugaredType(Context))) { | ||||
1749 | if (Ptr->getPointeeType()->hasAttr(attr::NoDeref)) | ||||
1750 | ExprEvalContexts.back().PossibleDerefs.insert(E); | ||||
1751 | } | ||||
1752 | } | ||||
1753 | } | ||||
1754 | |||||
1755 | ExprResult | ||||
1756 | Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, | ||||
1757 | SourceLocation OpLoc, const CXXScopeSpec &SS, | ||||
1758 | FieldDecl *Field, DeclAccessPair FoundDecl, | ||||
1759 | const DeclarationNameInfo &MemberNameInfo) { | ||||
1760 | // x.a is an l-value if 'a' has a reference type. Otherwise: | ||||
1761 | // x.a is an l-value/x-value/pr-value if the base is (and note | ||||
1762 | // that *x is always an l-value), except that if the base isn't | ||||
1763 | // an ordinary object then we must have an rvalue. | ||||
1764 | ExprValueKind VK = VK_LValue; | ||||
1765 | ExprObjectKind OK = OK_Ordinary; | ||||
1766 | if (!IsArrow) { | ||||
1767 | if (BaseExpr->getObjectKind() == OK_Ordinary) | ||||
1768 | VK = BaseExpr->getValueKind(); | ||||
1769 | else | ||||
1770 | VK = VK_RValue; | ||||
1771 | } | ||||
1772 | if (VK != VK_RValue && Field->isBitField()) | ||||
1773 | OK = OK_BitField; | ||||
1774 | |||||
1775 | // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref] | ||||
1776 | QualType MemberType = Field->getType(); | ||||
1777 | if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) { | ||||
1778 | MemberType = Ref->getPointeeType(); | ||||
1779 | VK = VK_LValue; | ||||
1780 | } else { | ||||
1781 | QualType BaseType = BaseExpr->getType(); | ||||
1782 | if (IsArrow) BaseType = BaseType->getAs<PointerType>()->getPointeeType(); | ||||
1783 | |||||
1784 | Qualifiers BaseQuals = BaseType.getQualifiers(); | ||||
1785 | |||||
1786 | // GC attributes are never picked up by members. | ||||
1787 | BaseQuals.removeObjCGCAttr(); | ||||
1788 | |||||
1789 | // CVR attributes from the base are picked up by members, | ||||
1790 | // except that 'mutable' members don't pick up 'const'. | ||||
1791 | if (Field->isMutable()) BaseQuals.removeConst(); | ||||
1792 | |||||
1793 | Qualifiers MemberQuals = | ||||
1794 | Context.getCanonicalType(MemberType).getQualifiers(); | ||||
1795 | |||||
1796 | assert(!MemberQuals.hasAddressSpace())((!MemberQuals.hasAddressSpace()) ? static_cast<void> ( 0) : __assert_fail ("!MemberQuals.hasAddressSpace()", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 1796, __PRETTY_FUNCTION__)); | ||||
1797 | |||||
1798 | Qualifiers Combined = BaseQuals + MemberQuals; | ||||
1799 | if (Combined != MemberQuals) | ||||
1800 | MemberType = Context.getQualifiedType(MemberType, Combined); | ||||
1801 | } | ||||
1802 | |||||
1803 | auto *CurMethod = dyn_cast<CXXMethodDecl>(CurContext); | ||||
1804 | if (!(CurMethod && CurMethod->isDefaulted())) | ||||
1805 | UnusedPrivateFields.remove(Field); | ||||
1806 | |||||
1807 | ExprResult Base = PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(), | ||||
1808 | FoundDecl, Field); | ||||
1809 | if (Base.isInvalid()) | ||||
1810 | return ExprError(); | ||||
1811 | |||||
1812 | // Build a reference to a private copy for non-static data members in | ||||
1813 | // non-static member functions, privatized by OpenMP constructs. | ||||
1814 | if (getLangOpts().OpenMP && IsArrow && | ||||
1815 | !CurContext->isDependentContext() && | ||||
1816 | isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) { | ||||
1817 | if (auto *PrivateCopy = isOpenMPCapturedDecl(Field)) { | ||||
1818 | return getOpenMPCapturedExpr(PrivateCopy, VK, OK, | ||||
1819 | MemberNameInfo.getLoc()); | ||||
1820 | } | ||||
1821 | } | ||||
1822 | |||||
1823 | return BuildMemberExpr(Base.get(), IsArrow, OpLoc, &SS, | ||||
1824 | /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl, | ||||
1825 | /*HadMultipleCandidates=*/false, MemberNameInfo, | ||||
1826 | MemberType, VK, OK); | ||||
1827 | } | ||||
1828 | |||||
1829 | /// Builds an implicit member access expression. The current context | ||||
1830 | /// is known to be an instance method, and the given unqualified lookup | ||||
1831 | /// set is known to contain only instance members, at least one of which | ||||
1832 | /// is from an appropriate type. | ||||
1833 | ExprResult | ||||
1834 | Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, | ||||
1835 | SourceLocation TemplateKWLoc, | ||||
1836 | LookupResult &R, | ||||
1837 | const TemplateArgumentListInfo *TemplateArgs, | ||||
1838 | bool IsKnownInstance, const Scope *S) { | ||||
1839 | assert(!R.empty() && !R.isAmbiguous())((!R.empty() && !R.isAmbiguous()) ? static_cast<void > (0) : __assert_fail ("!R.empty() && !R.isAmbiguous()" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 1839, __PRETTY_FUNCTION__)); | ||||
1840 | |||||
1841 | SourceLocation loc = R.getNameLoc(); | ||||
1842 | |||||
1843 | // If this is known to be an instance access, go ahead and build an | ||||
1844 | // implicit 'this' expression now. | ||||
1845 | // 'this' expression now. | ||||
1846 | QualType ThisTy = getCurrentThisType(); | ||||
1847 | assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'")((!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'" ) ? static_cast<void> (0) : __assert_fail ("!ThisTy.isNull() && \"didn't correctly pre-flight capture of 'this'\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/lib/Sema/SemaExprMember.cpp" , 1847, __PRETTY_FUNCTION__)); | ||||
1848 | |||||
1849 | Expr *baseExpr = nullptr; // null signifies implicit access | ||||
1850 | if (IsKnownInstance) { | ||||
1851 | SourceLocation Loc = R.getNameLoc(); | ||||
1852 | if (SS.getRange().isValid()) | ||||
1853 | Loc = SS.getRange().getBegin(); | ||||
1854 | baseExpr = BuildCXXThisExpr(loc, ThisTy, /*IsImplicit=*/true); | ||||
1855 | } | ||||
1856 | |||||
1857 | return BuildMemberReferenceExpr(baseExpr, ThisTy, | ||||
1858 | /*OpLoc*/ SourceLocation(), | ||||
1859 | /*IsArrow*/ true, | ||||
1860 | SS, TemplateKWLoc, | ||||
1861 | /*FirstQualifierInScope*/ nullptr, | ||||
1862 | R, TemplateArgs, S); | ||||
1863 | } |
1 | //===--- DeclSpec.h - Parsed declaration specifiers -------------*- C++ -*-===// |
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 | /// \file |
10 | /// This file defines the classes used to store parsed information about |
11 | /// declaration-specifiers and declarators. |
12 | /// |
13 | /// \verbatim |
14 | /// static const int volatile x, *y, *(*(*z)[10])(const void *x); |
15 | /// ------------------------- - -- --------------------------- |
16 | /// declaration-specifiers \ | / |
17 | /// declarators |
18 | /// \endverbatim |
19 | /// |
20 | //===----------------------------------------------------------------------===// |
21 | |
22 | #ifndef LLVM_CLANG_SEMA_DECLSPEC_H |
23 | #define LLVM_CLANG_SEMA_DECLSPEC_H |
24 | |
25 | #include "clang/AST/DeclCXX.h" |
26 | #include "clang/AST/NestedNameSpecifier.h" |
27 | #include "clang/Basic/ExceptionSpecificationType.h" |
28 | #include "clang/Basic/Lambda.h" |
29 | #include "clang/Basic/OperatorKinds.h" |
30 | #include "clang/Basic/Specifiers.h" |
31 | #include "clang/Lex/Token.h" |
32 | #include "clang/Sema/Ownership.h" |
33 | #include "clang/Sema/ParsedAttr.h" |
34 | #include "llvm/ADT/SmallVector.h" |
35 | #include "llvm/Support/Compiler.h" |
36 | #include "llvm/Support/ErrorHandling.h" |
37 | |
38 | namespace clang { |
39 | class ASTContext; |
40 | class CXXRecordDecl; |
41 | class TypeLoc; |
42 | class LangOptions; |
43 | class IdentifierInfo; |
44 | class NamespaceAliasDecl; |
45 | class NamespaceDecl; |
46 | class ObjCDeclSpec; |
47 | class Sema; |
48 | class Declarator; |
49 | struct TemplateIdAnnotation; |
50 | |
51 | /// Represents a C++ nested-name-specifier or a global scope specifier. |
52 | /// |
53 | /// These can be in 3 states: |
54 | /// 1) Not present, identified by isEmpty() |
55 | /// 2) Present, identified by isNotEmpty() |
56 | /// 2.a) Valid, identified by isValid() |
57 | /// 2.b) Invalid, identified by isInvalid(). |
58 | /// |
59 | /// isSet() is deprecated because it mostly corresponded to "valid" but was |
60 | /// often used as if it meant "present". |
61 | /// |
62 | /// The actual scope is described by getScopeRep(). |
63 | class CXXScopeSpec { |
64 | SourceRange Range; |
65 | NestedNameSpecifierLocBuilder Builder; |
66 | |
67 | public: |
68 | SourceRange getRange() const { return Range; } |
69 | void setRange(SourceRange R) { Range = R; } |
70 | void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); } |
71 | void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); } |
72 | SourceLocation getBeginLoc() const { return Range.getBegin(); } |
73 | SourceLocation getEndLoc() const { return Range.getEnd(); } |
74 | |
75 | /// Retrieve the representation of the nested-name-specifier. |
76 | NestedNameSpecifier *getScopeRep() const { |
77 | return Builder.getRepresentation(); |
78 | } |
79 | |
80 | /// Extend the current nested-name-specifier by another |
81 | /// nested-name-specifier component of the form 'type::'. |
82 | /// |
83 | /// \param Context The AST context in which this nested-name-specifier |
84 | /// resides. |
85 | /// |
86 | /// \param TemplateKWLoc The location of the 'template' keyword, if present. |
87 | /// |
88 | /// \param TL The TypeLoc that describes the type preceding the '::'. |
89 | /// |
90 | /// \param ColonColonLoc The location of the trailing '::'. |
91 | void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, |
92 | SourceLocation ColonColonLoc); |
93 | |
94 | /// Extend the current nested-name-specifier by another |
95 | /// nested-name-specifier component of the form 'identifier::'. |
96 | /// |
97 | /// \param Context The AST context in which this nested-name-specifier |
98 | /// resides. |
99 | /// |
100 | /// \param Identifier The identifier. |
101 | /// |
102 | /// \param IdentifierLoc The location of the identifier. |
103 | /// |
104 | /// \param ColonColonLoc The location of the trailing '::'. |
105 | void Extend(ASTContext &Context, IdentifierInfo *Identifier, |
106 | SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); |
107 | |
108 | /// Extend the current nested-name-specifier by another |
109 | /// nested-name-specifier component of the form 'namespace::'. |
110 | /// |
111 | /// \param Context The AST context in which this nested-name-specifier |
112 | /// resides. |
113 | /// |
114 | /// \param Namespace The namespace. |
115 | /// |
116 | /// \param NamespaceLoc The location of the namespace name. |
117 | /// |
118 | /// \param ColonColonLoc The location of the trailing '::'. |
119 | void Extend(ASTContext &Context, NamespaceDecl *Namespace, |
120 | SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); |
121 | |
122 | /// Extend the current nested-name-specifier by another |
123 | /// nested-name-specifier component of the form 'namespace-alias::'. |
124 | /// |
125 | /// \param Context The AST context in which this nested-name-specifier |
126 | /// resides. |
127 | /// |
128 | /// \param Alias The namespace alias. |
129 | /// |
130 | /// \param AliasLoc The location of the namespace alias |
131 | /// name. |
132 | /// |
133 | /// \param ColonColonLoc The location of the trailing '::'. |
134 | void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, |
135 | SourceLocation AliasLoc, SourceLocation ColonColonLoc); |
136 | |
137 | /// Turn this (empty) nested-name-specifier into the global |
138 | /// nested-name-specifier '::'. |
139 | void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); |
140 | |
141 | /// Turns this (empty) nested-name-specifier into '__super' |
142 | /// nested-name-specifier. |
143 | /// |
144 | /// \param Context The AST context in which this nested-name-specifier |
145 | /// resides. |
146 | /// |
147 | /// \param RD The declaration of the class in which nested-name-specifier |
148 | /// appeared. |
149 | /// |
150 | /// \param SuperLoc The location of the '__super' keyword. |
151 | /// name. |
152 | /// |
153 | /// \param ColonColonLoc The location of the trailing '::'. |
154 | void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, |
155 | SourceLocation SuperLoc, SourceLocation ColonColonLoc); |
156 | |
157 | /// Make a new nested-name-specifier from incomplete source-location |
158 | /// information. |
159 | /// |
160 | /// FIXME: This routine should be used very, very rarely, in cases where we |
161 | /// need to synthesize a nested-name-specifier. Most code should instead use |
162 | /// \c Adopt() with a proper \c NestedNameSpecifierLoc. |
163 | void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, |
164 | SourceRange R); |
165 | |
166 | /// Adopt an existing nested-name-specifier (with source-range |
167 | /// information). |
168 | void Adopt(NestedNameSpecifierLoc Other); |
169 | |
170 | /// Retrieve a nested-name-specifier with location information, copied |
171 | /// into the given AST context. |
172 | /// |
173 | /// \param Context The context into which this nested-name-specifier will be |
174 | /// copied. |
175 | NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; |
176 | |
177 | /// Retrieve the location of the name in the last qualifier |
178 | /// in this nested name specifier. |
179 | /// |
180 | /// For example, the location of \c bar |
181 | /// in |
182 | /// \verbatim |
183 | /// \::foo::bar<0>:: |
184 | /// ^~~ |
185 | /// \endverbatim |
186 | SourceLocation getLastQualifierNameLoc() const; |
187 | |
188 | /// No scope specifier. |
189 | bool isEmpty() const { return !Range.isValid(); } |
190 | /// A scope specifier is present, but may be valid or invalid. |
191 | bool isNotEmpty() const { return !isEmpty(); } |
192 | |
193 | /// An error occurred during parsing of the scope specifier. |
194 | bool isInvalid() const { return isNotEmpty() && getScopeRep() == nullptr; } |
195 | /// A scope specifier is present, and it refers to a real scope. |
196 | bool isValid() const { return isNotEmpty() && getScopeRep() != nullptr; } |
197 | |
198 | /// Indicate that this nested-name-specifier is invalid. |
199 | void SetInvalid(SourceRange R) { |
200 | assert(R.isValid() && "Must have a valid source range")((R.isValid() && "Must have a valid source range") ? static_cast <void> (0) : __assert_fail ("R.isValid() && \"Must have a valid source range\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 200, __PRETTY_FUNCTION__)); |
201 | if (Range.getBegin().isInvalid()) |
202 | Range.setBegin(R.getBegin()); |
203 | Range.setEnd(R.getEnd()); |
204 | Builder.Clear(); |
205 | } |
206 | |
207 | /// Deprecated. Some call sites intend isNotEmpty() while others intend |
208 | /// isValid(). |
209 | bool isSet() const { return getScopeRep() != nullptr; } |
210 | |
211 | void clear() { |
212 | Range = SourceRange(); |
213 | Builder.Clear(); |
214 | } |
215 | |
216 | /// Retrieve the data associated with the source-location information. |
217 | char *location_data() const { return Builder.getBuffer().first; } |
218 | |
219 | /// Retrieve the size of the data associated with source-location |
220 | /// information. |
221 | unsigned location_size() const { return Builder.getBuffer().second; } |
222 | }; |
223 | |
224 | /// Captures information about "declaration specifiers". |
225 | /// |
226 | /// "Declaration specifiers" encompasses storage-class-specifiers, |
227 | /// type-specifiers, type-qualifiers, and function-specifiers. |
228 | class DeclSpec { |
229 | public: |
230 | /// storage-class-specifier |
231 | /// \note The order of these enumerators is important for diagnostics. |
232 | enum SCS { |
233 | SCS_unspecified = 0, |
234 | SCS_typedef, |
235 | SCS_extern, |
236 | SCS_static, |
237 | SCS_auto, |
238 | SCS_register, |
239 | SCS_private_extern, |
240 | SCS_mutable |
241 | }; |
242 | |
243 | // Import thread storage class specifier enumeration and constants. |
244 | // These can be combined with SCS_extern and SCS_static. |
245 | typedef ThreadStorageClassSpecifier TSCS; |
246 | static const TSCS TSCS_unspecified = clang::TSCS_unspecified; |
247 | static const TSCS TSCS___thread = clang::TSCS___thread; |
248 | static const TSCS TSCS_thread_local = clang::TSCS_thread_local; |
249 | static const TSCS TSCS__Thread_local = clang::TSCS__Thread_local; |
250 | |
251 | // Import type specifier width enumeration and constants. |
252 | typedef TypeSpecifierWidth TSW; |
253 | static const TSW TSW_unspecified = clang::TSW_unspecified; |
254 | static const TSW TSW_short = clang::TSW_short; |
255 | static const TSW TSW_long = clang::TSW_long; |
256 | static const TSW TSW_longlong = clang::TSW_longlong; |
257 | |
258 | enum TSC { |
259 | TSC_unspecified, |
260 | TSC_imaginary, |
261 | TSC_complex |
262 | }; |
263 | |
264 | // Import type specifier sign enumeration and constants. |
265 | typedef TypeSpecifierSign TSS; |
266 | static const TSS TSS_unspecified = clang::TSS_unspecified; |
267 | static const TSS TSS_signed = clang::TSS_signed; |
268 | static const TSS TSS_unsigned = clang::TSS_unsigned; |
269 | |
270 | // Import type specifier type enumeration and constants. |
271 | typedef TypeSpecifierType TST; |
272 | static const TST TST_unspecified = clang::TST_unspecified; |
273 | static const TST TST_void = clang::TST_void; |
274 | static const TST TST_char = clang::TST_char; |
275 | static const TST TST_wchar = clang::TST_wchar; |
276 | static const TST TST_char8 = clang::TST_char8; |
277 | static const TST TST_char16 = clang::TST_char16; |
278 | static const TST TST_char32 = clang::TST_char32; |
279 | static const TST TST_int = clang::TST_int; |
280 | static const TST TST_int128 = clang::TST_int128; |
281 | static const TST TST_half = clang::TST_half; |
282 | static const TST TST_float = clang::TST_float; |
283 | static const TST TST_double = clang::TST_double; |
284 | static const TST TST_float16 = clang::TST_Float16; |
285 | static const TST TST_accum = clang::TST_Accum; |
286 | static const TST TST_fract = clang::TST_Fract; |
287 | static const TST TST_float128 = clang::TST_float128; |
288 | static const TST TST_bool = clang::TST_bool; |
289 | static const TST TST_decimal32 = clang::TST_decimal32; |
290 | static const TST TST_decimal64 = clang::TST_decimal64; |
291 | static const TST TST_decimal128 = clang::TST_decimal128; |
292 | static const TST TST_enum = clang::TST_enum; |
293 | static const TST TST_union = clang::TST_union; |
294 | static const TST TST_struct = clang::TST_struct; |
295 | static const TST TST_interface = clang::TST_interface; |
296 | static const TST TST_class = clang::TST_class; |
297 | static const TST TST_typename = clang::TST_typename; |
298 | static const TST TST_typeofType = clang::TST_typeofType; |
299 | static const TST TST_typeofExpr = clang::TST_typeofExpr; |
300 | static const TST TST_decltype = clang::TST_decltype; |
301 | static const TST TST_decltype_auto = clang::TST_decltype_auto; |
302 | static const TST TST_underlyingType = clang::TST_underlyingType; |
303 | static const TST TST_auto = clang::TST_auto; |
304 | static const TST TST_auto_type = clang::TST_auto_type; |
305 | static const TST TST_unknown_anytype = clang::TST_unknown_anytype; |
306 | static const TST TST_atomic = clang::TST_atomic; |
307 | #define GENERIC_IMAGE_TYPE(ImgType, Id) \ |
308 | static const TST TST_##ImgType##_t = clang::TST_##ImgType##_t; |
309 | #include "clang/Basic/OpenCLImageTypes.def" |
310 | static const TST TST_error = clang::TST_error; |
311 | |
312 | // type-qualifiers |
313 | enum TQ { // NOTE: These flags must be kept in sync with Qualifiers::TQ. |
314 | TQ_unspecified = 0, |
315 | TQ_const = 1, |
316 | TQ_restrict = 2, |
317 | TQ_volatile = 4, |
318 | TQ_unaligned = 8, |
319 | // This has no corresponding Qualifiers::TQ value, because it's not treated |
320 | // as a qualifier in our type system. |
321 | TQ_atomic = 16 |
322 | }; |
323 | |
324 | /// ParsedSpecifiers - Flags to query which specifiers were applied. This is |
325 | /// returned by getParsedSpecifiers. |
326 | enum ParsedSpecifiers { |
327 | PQ_None = 0, |
328 | PQ_StorageClassSpecifier = 1, |
329 | PQ_TypeSpecifier = 2, |
330 | PQ_TypeQualifier = 4, |
331 | PQ_FunctionSpecifier = 8 |
332 | // FIXME: Attributes should be included here. |
333 | }; |
334 | |
335 | private: |
336 | // storage-class-specifier |
337 | /*SCS*/unsigned StorageClassSpec : 3; |
338 | /*TSCS*/unsigned ThreadStorageClassSpec : 2; |
339 | unsigned SCS_extern_in_linkage_spec : 1; |
340 | |
341 | // type-specifier |
342 | /*TSW*/unsigned TypeSpecWidth : 2; |
343 | /*TSC*/unsigned TypeSpecComplex : 2; |
344 | /*TSS*/unsigned TypeSpecSign : 2; |
345 | /*TST*/unsigned TypeSpecType : 6; |
346 | unsigned TypeAltiVecVector : 1; |
347 | unsigned TypeAltiVecPixel : 1; |
348 | unsigned TypeAltiVecBool : 1; |
349 | unsigned TypeSpecOwned : 1; |
350 | unsigned TypeSpecPipe : 1; |
351 | unsigned TypeSpecSat : 1; |
352 | |
353 | // type-qualifiers |
354 | unsigned TypeQualifiers : 5; // Bitwise OR of TQ. |
355 | |
356 | // function-specifier |
357 | unsigned FS_inline_specified : 1; |
358 | unsigned FS_forceinline_specified: 1; |
359 | unsigned FS_virtual_specified : 1; |
360 | unsigned FS_noreturn_specified : 1; |
361 | |
362 | // friend-specifier |
363 | unsigned Friend_specified : 1; |
364 | |
365 | // constexpr-specifier |
366 | unsigned ConstexprSpecifier : 2; |
367 | |
368 | union { |
369 | UnionParsedType TypeRep; |
370 | Decl *DeclRep; |
371 | Expr *ExprRep; |
372 | }; |
373 | |
374 | /// ExplicitSpecifier - Store information about explicit spicifer. |
375 | ExplicitSpecifier FS_explicit_specifier; |
376 | |
377 | // attributes. |
378 | ParsedAttributes Attrs; |
379 | |
380 | // Scope specifier for the type spec, if applicable. |
381 | CXXScopeSpec TypeScope; |
382 | |
383 | // SourceLocation info. These are null if the item wasn't specified or if |
384 | // the setting was synthesized. |
385 | SourceRange Range; |
386 | |
387 | SourceLocation StorageClassSpecLoc, ThreadStorageClassSpecLoc; |
388 | SourceRange TSWRange; |
389 | SourceLocation TSCLoc, TSSLoc, TSTLoc, AltiVecLoc, TSSatLoc; |
390 | /// TSTNameLoc - If TypeSpecType is any of class, enum, struct, union, |
391 | /// typename, then this is the location of the named type (if present); |
392 | /// otherwise, it is the same as TSTLoc. Hence, the pair TSTLoc and |
393 | /// TSTNameLoc provides source range info for tag types. |
394 | SourceLocation TSTNameLoc; |
395 | SourceRange TypeofParensRange; |
396 | SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc, |
397 | TQ_unalignedLoc; |
398 | SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc; |
399 | SourceLocation FS_explicitCloseParenLoc; |
400 | SourceLocation FS_forceinlineLoc; |
401 | SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc; |
402 | SourceLocation TQ_pipeLoc; |
403 | |
404 | WrittenBuiltinSpecs writtenBS; |
405 | void SaveWrittenBuiltinSpecs(); |
406 | |
407 | ObjCDeclSpec *ObjCQualifiers; |
408 | |
409 | static bool isTypeRep(TST T) { |
410 | return (T == TST_typename || T == TST_typeofType || |
411 | T == TST_underlyingType || T == TST_atomic); |
412 | } |
413 | static bool isExprRep(TST T) { |
414 | return (T == TST_typeofExpr || T == TST_decltype); |
415 | } |
416 | |
417 | DeclSpec(const DeclSpec &) = delete; |
418 | void operator=(const DeclSpec &) = delete; |
419 | public: |
420 | static bool isDeclRep(TST T) { |
421 | return (T == TST_enum || T == TST_struct || |
422 | T == TST_interface || T == TST_union || |
423 | T == TST_class); |
424 | } |
425 | |
426 | DeclSpec(AttributeFactory &attrFactory) |
427 | : StorageClassSpec(SCS_unspecified), |
428 | ThreadStorageClassSpec(TSCS_unspecified), |
429 | SCS_extern_in_linkage_spec(false), TypeSpecWidth(TSW_unspecified), |
430 | TypeSpecComplex(TSC_unspecified), TypeSpecSign(TSS_unspecified), |
431 | TypeSpecType(TST_unspecified), TypeAltiVecVector(false), |
432 | TypeAltiVecPixel(false), TypeAltiVecBool(false), TypeSpecOwned(false), |
433 | TypeSpecPipe(false), TypeSpecSat(false), TypeQualifiers(TQ_unspecified), |
434 | FS_inline_specified(false), FS_forceinline_specified(false), |
435 | FS_virtual_specified(false), FS_noreturn_specified(false), |
436 | Friend_specified(false), ConstexprSpecifier(CSK_unspecified), |
437 | FS_explicit_specifier(), Attrs(attrFactory), writtenBS(), |
438 | ObjCQualifiers(nullptr) {} |
439 | |
440 | // storage-class-specifier |
441 | SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; } |
442 | TSCS getThreadStorageClassSpec() const { |
443 | return (TSCS)ThreadStorageClassSpec; |
444 | } |
445 | bool isExternInLinkageSpec() const { return SCS_extern_in_linkage_spec; } |
446 | void setExternInLinkageSpec(bool Value) { |
447 | SCS_extern_in_linkage_spec = Value; |
448 | } |
449 | |
450 | SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; } |
451 | SourceLocation getThreadStorageClassSpecLoc() const { |
452 | return ThreadStorageClassSpecLoc; |
453 | } |
454 | |
455 | void ClearStorageClassSpecs() { |
456 | StorageClassSpec = DeclSpec::SCS_unspecified; |
457 | ThreadStorageClassSpec = DeclSpec::TSCS_unspecified; |
458 | SCS_extern_in_linkage_spec = false; |
459 | StorageClassSpecLoc = SourceLocation(); |
460 | ThreadStorageClassSpecLoc = SourceLocation(); |
461 | } |
462 | |
463 | void ClearTypeSpecType() { |
464 | TypeSpecType = DeclSpec::TST_unspecified; |
465 | TypeSpecOwned = false; |
466 | TSTLoc = SourceLocation(); |
467 | } |
468 | |
469 | // type-specifier |
470 | TSW getTypeSpecWidth() const { return (TSW)TypeSpecWidth; } |
471 | TSC getTypeSpecComplex() const { return (TSC)TypeSpecComplex; } |
472 | TSS getTypeSpecSign() const { return (TSS)TypeSpecSign; } |
473 | TST getTypeSpecType() const { return (TST)TypeSpecType; } |
474 | bool isTypeAltiVecVector() const { return TypeAltiVecVector; } |
475 | bool isTypeAltiVecPixel() const { return TypeAltiVecPixel; } |
476 | bool isTypeAltiVecBool() const { return TypeAltiVecBool; } |
477 | bool isTypeSpecOwned() const { return TypeSpecOwned; } |
478 | bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); } |
479 | bool isTypeSpecPipe() const { return TypeSpecPipe; } |
480 | bool isTypeSpecSat() const { return TypeSpecSat; } |
481 | |
482 | ParsedType getRepAsType() const { |
483 | assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type")((isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type" ) ? static_cast<void> (0) : __assert_fail ("isTypeRep((TST) TypeSpecType) && \"DeclSpec does not store a type\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 483, __PRETTY_FUNCTION__)); |
484 | return TypeRep; |
485 | } |
486 | Decl *getRepAsDecl() const { |
487 | assert(isDeclRep((TST) TypeSpecType) && "DeclSpec does not store a decl")((isDeclRep((TST) TypeSpecType) && "DeclSpec does not store a decl" ) ? static_cast<void> (0) : __assert_fail ("isDeclRep((TST) TypeSpecType) && \"DeclSpec does not store a decl\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 487, __PRETTY_FUNCTION__)); |
488 | return DeclRep; |
489 | } |
490 | Expr *getRepAsExpr() const { |
491 | assert(isExprRep((TST) TypeSpecType) && "DeclSpec does not store an expr")((isExprRep((TST) TypeSpecType) && "DeclSpec does not store an expr" ) ? static_cast<void> (0) : __assert_fail ("isExprRep((TST) TypeSpecType) && \"DeclSpec does not store an expr\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 491, __PRETTY_FUNCTION__)); |
492 | return ExprRep; |
493 | } |
494 | CXXScopeSpec &getTypeSpecScope() { return TypeScope; } |
495 | const CXXScopeSpec &getTypeSpecScope() const { return TypeScope; } |
496 | |
497 | SourceRange getSourceRange() const LLVM_READONLY__attribute__((__pure__)) { return Range; } |
498 | SourceLocation getBeginLoc() const LLVM_READONLY__attribute__((__pure__)) { return Range.getBegin(); } |
499 | SourceLocation getEndLoc() const LLVM_READONLY__attribute__((__pure__)) { return Range.getEnd(); } |
500 | |
501 | SourceLocation getTypeSpecWidthLoc() const { return TSWRange.getBegin(); } |
502 | SourceRange getTypeSpecWidthRange() const { return TSWRange; } |
503 | SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; } |
504 | SourceLocation getTypeSpecSignLoc() const { return TSSLoc; } |
505 | SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; } |
506 | SourceLocation getAltiVecLoc() const { return AltiVecLoc; } |
507 | SourceLocation getTypeSpecSatLoc() const { return TSSatLoc; } |
508 | |
509 | SourceLocation getTypeSpecTypeNameLoc() const { |
510 | assert(isDeclRep((TST) TypeSpecType) || TypeSpecType == TST_typename)((isDeclRep((TST) TypeSpecType) || TypeSpecType == TST_typename ) ? static_cast<void> (0) : __assert_fail ("isDeclRep((TST) TypeSpecType) || TypeSpecType == TST_typename" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 510, __PRETTY_FUNCTION__)); |
511 | return TSTNameLoc; |
512 | } |
513 | |
514 | SourceRange getTypeofParensRange() const { return TypeofParensRange; } |
515 | void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; } |
516 | |
517 | bool hasAutoTypeSpec() const { |
518 | return (TypeSpecType == TST_auto || TypeSpecType == TST_auto_type || |
519 | TypeSpecType == TST_decltype_auto); |
520 | } |
521 | |
522 | bool hasTagDefinition() const; |
523 | |
524 | /// Turn a type-specifier-type into a string like "_Bool" or "union". |
525 | static const char *getSpecifierName(DeclSpec::TST T, |
526 | const PrintingPolicy &Policy); |
527 | static const char *getSpecifierName(DeclSpec::TQ Q); |
528 | static const char *getSpecifierName(DeclSpec::TSS S); |
529 | static const char *getSpecifierName(DeclSpec::TSC C); |
530 | static const char *getSpecifierName(DeclSpec::TSW W); |
531 | static const char *getSpecifierName(DeclSpec::SCS S); |
532 | static const char *getSpecifierName(DeclSpec::TSCS S); |
533 | static const char *getSpecifierName(ConstexprSpecKind C); |
534 | |
535 | // type-qualifiers |
536 | |
537 | /// getTypeQualifiers - Return a set of TQs. |
538 | unsigned getTypeQualifiers() const { return TypeQualifiers; } |
539 | SourceLocation getConstSpecLoc() const { return TQ_constLoc; } |
540 | SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; } |
541 | SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; } |
542 | SourceLocation getAtomicSpecLoc() const { return TQ_atomicLoc; } |
543 | SourceLocation getUnalignedSpecLoc() const { return TQ_unalignedLoc; } |
544 | SourceLocation getPipeLoc() const { return TQ_pipeLoc; } |
545 | |
546 | /// Clear out all of the type qualifiers. |
547 | void ClearTypeQualifiers() { |
548 | TypeQualifiers = 0; |
549 | TQ_constLoc = SourceLocation(); |
550 | TQ_restrictLoc = SourceLocation(); |
551 | TQ_volatileLoc = SourceLocation(); |
552 | TQ_atomicLoc = SourceLocation(); |
553 | TQ_unalignedLoc = SourceLocation(); |
554 | TQ_pipeLoc = SourceLocation(); |
555 | } |
556 | |
557 | // function-specifier |
558 | bool isInlineSpecified() const { |
559 | return FS_inline_specified | FS_forceinline_specified; |
560 | } |
561 | SourceLocation getInlineSpecLoc() const { |
562 | return FS_inline_specified ? FS_inlineLoc : FS_forceinlineLoc; |
563 | } |
564 | |
565 | ExplicitSpecifier getExplicitSpecifier() const { |
566 | return FS_explicit_specifier; |
567 | } |
568 | |
569 | bool isVirtualSpecified() const { return FS_virtual_specified; } |
570 | SourceLocation getVirtualSpecLoc() const { return FS_virtualLoc; } |
571 | |
572 | bool hasExplicitSpecifier() const { |
573 | return FS_explicit_specifier.isSpecified(); |
574 | } |
575 | SourceLocation getExplicitSpecLoc() const { return FS_explicitLoc; } |
576 | SourceRange getExplicitSpecRange() const { |
577 | return FS_explicit_specifier.getExpr() |
578 | ? SourceRange(FS_explicitLoc, FS_explicitCloseParenLoc) |
579 | : SourceRange(FS_explicitLoc); |
580 | } |
581 | |
582 | bool isNoreturnSpecified() const { return FS_noreturn_specified; } |
583 | SourceLocation getNoreturnSpecLoc() const { return FS_noreturnLoc; } |
584 | |
585 | void ClearFunctionSpecs() { |
586 | FS_inline_specified = false; |
587 | FS_inlineLoc = SourceLocation(); |
588 | FS_forceinline_specified = false; |
589 | FS_forceinlineLoc = SourceLocation(); |
590 | FS_virtual_specified = false; |
591 | FS_virtualLoc = SourceLocation(); |
592 | FS_explicit_specifier = ExplicitSpecifier(); |
593 | FS_explicitLoc = SourceLocation(); |
594 | FS_explicitCloseParenLoc = SourceLocation(); |
595 | FS_noreturn_specified = false; |
596 | FS_noreturnLoc = SourceLocation(); |
597 | } |
598 | |
599 | /// This method calls the passed in handler on each CVRU qual being |
600 | /// set. |
601 | /// Handle - a handler to be invoked. |
602 | void forEachCVRUQualifier( |
603 | llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle); |
604 | |
605 | /// This method calls the passed in handler on each qual being |
606 | /// set. |
607 | /// Handle - a handler to be invoked. |
608 | void forEachQualifier( |
609 | llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle); |
610 | |
611 | /// Return true if any type-specifier has been found. |
612 | bool hasTypeSpecifier() const { |
613 | return getTypeSpecType() != DeclSpec::TST_unspecified || |
614 | getTypeSpecWidth() != DeclSpec::TSW_unspecified || |
615 | getTypeSpecComplex() != DeclSpec::TSC_unspecified || |
616 | getTypeSpecSign() != DeclSpec::TSS_unspecified; |
617 | } |
618 | |
619 | /// Return a bitmask of which flavors of specifiers this |
620 | /// DeclSpec includes. |
621 | unsigned getParsedSpecifiers() const; |
622 | |
623 | /// isEmpty - Return true if this declaration specifier is completely empty: |
624 | /// no tokens were parsed in the production of it. |
625 | bool isEmpty() const { |
626 | return getParsedSpecifiers() == DeclSpec::PQ_None; |
627 | } |
628 | |
629 | void SetRangeStart(SourceLocation Loc) { Range.setBegin(Loc); } |
630 | void SetRangeEnd(SourceLocation Loc) { Range.setEnd(Loc); } |
631 | |
632 | /// These methods set the specified attribute of the DeclSpec and |
633 | /// return false if there was no error. If an error occurs (for |
634 | /// example, if we tried to set "auto" on a spec with "extern" |
635 | /// already set), they return true and set PrevSpec and DiagID |
636 | /// such that |
637 | /// Diag(Loc, DiagID) << PrevSpec; |
638 | /// will yield a useful result. |
639 | /// |
640 | /// TODO: use a more general approach that still allows these |
641 | /// diagnostics to be ignored when desired. |
642 | bool SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc, |
643 | const char *&PrevSpec, unsigned &DiagID, |
644 | const PrintingPolicy &Policy); |
645 | bool SetStorageClassSpecThread(TSCS TSC, SourceLocation Loc, |
646 | const char *&PrevSpec, unsigned &DiagID); |
647 | bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec, |
648 | unsigned &DiagID, const PrintingPolicy &Policy); |
649 | bool SetTypeSpecComplex(TSC C, SourceLocation Loc, const char *&PrevSpec, |
650 | unsigned &DiagID); |
651 | bool SetTypeSpecSign(TSS S, SourceLocation Loc, const char *&PrevSpec, |
652 | unsigned &DiagID); |
653 | bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, |
654 | unsigned &DiagID, const PrintingPolicy &Policy); |
655 | bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, |
656 | unsigned &DiagID, ParsedType Rep, |
657 | const PrintingPolicy &Policy); |
658 | bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, |
659 | unsigned &DiagID, Decl *Rep, bool Owned, |
660 | const PrintingPolicy &Policy); |
661 | bool SetTypeSpecType(TST T, SourceLocation TagKwLoc, |
662 | SourceLocation TagNameLoc, const char *&PrevSpec, |
663 | unsigned &DiagID, ParsedType Rep, |
664 | const PrintingPolicy &Policy); |
665 | bool SetTypeSpecType(TST T, SourceLocation TagKwLoc, |
666 | SourceLocation TagNameLoc, const char *&PrevSpec, |
667 | unsigned &DiagID, Decl *Rep, bool Owned, |
668 | const PrintingPolicy &Policy); |
669 | |
670 | bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, |
671 | unsigned &DiagID, Expr *Rep, |
672 | const PrintingPolicy &policy); |
673 | bool SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, |
674 | const char *&PrevSpec, unsigned &DiagID, |
675 | const PrintingPolicy &Policy); |
676 | bool SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, |
677 | const char *&PrevSpec, unsigned &DiagID, |
678 | const PrintingPolicy &Policy); |
679 | bool SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc, |
680 | const char *&PrevSpec, unsigned &DiagID, |
681 | const PrintingPolicy &Policy); |
682 | bool SetTypePipe(bool isPipe, SourceLocation Loc, |
683 | const char *&PrevSpec, unsigned &DiagID, |
684 | const PrintingPolicy &Policy); |
685 | bool SetTypeSpecSat(SourceLocation Loc, const char *&PrevSpec, |
686 | unsigned &DiagID); |
687 | bool SetTypeSpecError(); |
688 | void UpdateDeclRep(Decl *Rep) { |
689 | assert(isDeclRep((TST) TypeSpecType))((isDeclRep((TST) TypeSpecType)) ? static_cast<void> (0 ) : __assert_fail ("isDeclRep((TST) TypeSpecType)", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 689, __PRETTY_FUNCTION__)); |
690 | DeclRep = Rep; |
691 | } |
692 | void UpdateTypeRep(ParsedType Rep) { |
693 | assert(isTypeRep((TST) TypeSpecType))((isTypeRep((TST) TypeSpecType)) ? static_cast<void> (0 ) : __assert_fail ("isTypeRep((TST) TypeSpecType)", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 693, __PRETTY_FUNCTION__)); |
694 | TypeRep = Rep; |
695 | } |
696 | void UpdateExprRep(Expr *Rep) { |
697 | assert(isExprRep((TST) TypeSpecType))((isExprRep((TST) TypeSpecType)) ? static_cast<void> (0 ) : __assert_fail ("isExprRep((TST) TypeSpecType)", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 697, __PRETTY_FUNCTION__)); |
698 | ExprRep = Rep; |
699 | } |
700 | |
701 | bool SetTypeQual(TQ T, SourceLocation Loc); |
702 | |
703 | bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, |
704 | unsigned &DiagID, const LangOptions &Lang); |
705 | |
706 | bool setFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec, |
707 | unsigned &DiagID); |
708 | bool setFunctionSpecForceInline(SourceLocation Loc, const char *&PrevSpec, |
709 | unsigned &DiagID); |
710 | bool setFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec, |
711 | unsigned &DiagID); |
712 | bool setFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec, |
713 | unsigned &DiagID, ExplicitSpecifier ExplicitSpec, |
714 | SourceLocation CloseParenLoc); |
715 | bool setFunctionSpecNoreturn(SourceLocation Loc, const char *&PrevSpec, |
716 | unsigned &DiagID); |
717 | |
718 | bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, |
719 | unsigned &DiagID); |
720 | bool setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec, |
721 | unsigned &DiagID); |
722 | bool SetConstexprSpec(ConstexprSpecKind ConstexprKind, SourceLocation Loc, |
723 | const char *&PrevSpec, unsigned &DiagID); |
724 | |
725 | bool isFriendSpecified() const { return Friend_specified; } |
726 | SourceLocation getFriendSpecLoc() const { return FriendLoc; } |
727 | |
728 | bool isModulePrivateSpecified() const { return ModulePrivateLoc.isValid(); } |
729 | SourceLocation getModulePrivateSpecLoc() const { return ModulePrivateLoc; } |
730 | |
731 | ConstexprSpecKind getConstexprSpecifier() const { |
732 | return ConstexprSpecKind(ConstexprSpecifier); |
733 | } |
734 | |
735 | SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; } |
736 | bool hasConstexprSpecifier() const { |
737 | return ConstexprSpecifier != CSK_unspecified; |
738 | } |
739 | |
740 | void ClearConstexprSpec() { |
741 | ConstexprSpecifier = CSK_unspecified; |
742 | ConstexprLoc = SourceLocation(); |
743 | } |
744 | |
745 | AttributePool &getAttributePool() const { |
746 | return Attrs.getPool(); |
747 | } |
748 | |
749 | /// Concatenates two attribute lists. |
750 | /// |
751 | /// The GCC attribute syntax allows for the following: |
752 | /// |
753 | /// \code |
754 | /// short __attribute__(( unused, deprecated )) |
755 | /// int __attribute__(( may_alias, aligned(16) )) var; |
756 | /// \endcode |
757 | /// |
758 | /// This declares 4 attributes using 2 lists. The following syntax is |
759 | /// also allowed and equivalent to the previous declaration. |
760 | /// |
761 | /// \code |
762 | /// short __attribute__((unused)) __attribute__((deprecated)) |
763 | /// int __attribute__((may_alias)) __attribute__((aligned(16))) var; |
764 | /// \endcode |
765 | /// |
766 | void addAttributes(ParsedAttributesView &AL) { |
767 | Attrs.addAll(AL.begin(), AL.end()); |
768 | } |
769 | |
770 | bool hasAttributes() const { return !Attrs.empty(); } |
771 | |
772 | ParsedAttributes &getAttributes() { return Attrs; } |
773 | const ParsedAttributes &getAttributes() const { return Attrs; } |
774 | |
775 | void takeAttributesFrom(ParsedAttributes &attrs) { |
776 | Attrs.takeAllFrom(attrs); |
777 | } |
778 | |
779 | /// Finish - This does final analysis of the declspec, issuing diagnostics for |
780 | /// things like "_Imaginary" (lacking an FP type). After calling this method, |
781 | /// DeclSpec is guaranteed self-consistent, even if an error occurred. |
782 | void Finish(Sema &S, const PrintingPolicy &Policy); |
783 | |
784 | const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const { |
785 | return writtenBS; |
786 | } |
787 | |
788 | ObjCDeclSpec *getObjCQualifiers() const { return ObjCQualifiers; } |
789 | void setObjCQualifiers(ObjCDeclSpec *quals) { ObjCQualifiers = quals; } |
790 | |
791 | /// Checks if this DeclSpec can stand alone, without a Declarator. |
792 | /// |
793 | /// Only tag declspecs can stand alone. |
794 | bool isMissingDeclaratorOk(); |
795 | }; |
796 | |
797 | /// Captures information about "declaration specifiers" specific to |
798 | /// Objective-C. |
799 | class ObjCDeclSpec { |
800 | public: |
801 | /// ObjCDeclQualifier - Qualifier used on types in method |
802 | /// declarations. Not all combinations are sensible. Parameters |
803 | /// can be one of { in, out, inout } with one of { bycopy, byref }. |
804 | /// Returns can either be { oneway } or not. |
805 | /// |
806 | /// This should be kept in sync with Decl::ObjCDeclQualifier. |
807 | enum ObjCDeclQualifier { |
808 | DQ_None = 0x0, |
809 | DQ_In = 0x1, |
810 | DQ_Inout = 0x2, |
811 | DQ_Out = 0x4, |
812 | DQ_Bycopy = 0x8, |
813 | DQ_Byref = 0x10, |
814 | DQ_Oneway = 0x20, |
815 | DQ_CSNullability = 0x40 |
816 | }; |
817 | |
818 | /// PropertyAttributeKind - list of property attributes. |
819 | /// Keep this list in sync with LLVM's Dwarf.h ApplePropertyAttributes. |
820 | enum ObjCPropertyAttributeKind { |
821 | DQ_PR_noattr = 0x0, |
822 | DQ_PR_readonly = 0x01, |
823 | DQ_PR_getter = 0x02, |
824 | DQ_PR_assign = 0x04, |
825 | DQ_PR_readwrite = 0x08, |
826 | DQ_PR_retain = 0x10, |
827 | DQ_PR_copy = 0x20, |
828 | DQ_PR_nonatomic = 0x40, |
829 | DQ_PR_setter = 0x80, |
830 | DQ_PR_atomic = 0x100, |
831 | DQ_PR_weak = 0x200, |
832 | DQ_PR_strong = 0x400, |
833 | DQ_PR_unsafe_unretained = 0x800, |
834 | DQ_PR_nullability = 0x1000, |
835 | DQ_PR_null_resettable = 0x2000, |
836 | DQ_PR_class = 0x4000 |
837 | }; |
838 | |
839 | ObjCDeclSpec() |
840 | : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr), |
841 | Nullability(0), GetterName(nullptr), SetterName(nullptr) { } |
842 | |
843 | ObjCDeclQualifier getObjCDeclQualifier() const { |
844 | return (ObjCDeclQualifier)objcDeclQualifier; |
845 | } |
846 | void setObjCDeclQualifier(ObjCDeclQualifier DQVal) { |
847 | objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); |
848 | } |
849 | void clearObjCDeclQualifier(ObjCDeclQualifier DQVal) { |
850 | objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier & ~DQVal); |
851 | } |
852 | |
853 | ObjCPropertyAttributeKind getPropertyAttributes() const { |
854 | return ObjCPropertyAttributeKind(PropertyAttributes); |
855 | } |
856 | void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) { |
857 | PropertyAttributes = |
858 | (ObjCPropertyAttributeKind)(PropertyAttributes | PRVal); |
859 | } |
860 | |
861 | NullabilityKind getNullability() const { |
862 | assert(((getObjCDeclQualifier() & DQ_CSNullability) ||((((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes () & DQ_PR_nullability)) && "Objective-C declspec doesn't have nullability" ) ? static_cast<void> (0) : __assert_fail ("((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes() & DQ_PR_nullability)) && \"Objective-C declspec doesn't have nullability\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 864, __PRETTY_FUNCTION__)) |
863 | (getPropertyAttributes() & DQ_PR_nullability)) &&((((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes () & DQ_PR_nullability)) && "Objective-C declspec doesn't have nullability" ) ? static_cast<void> (0) : __assert_fail ("((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes() & DQ_PR_nullability)) && \"Objective-C declspec doesn't have nullability\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 864, __PRETTY_FUNCTION__)) |
864 | "Objective-C declspec doesn't have nullability")((((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes () & DQ_PR_nullability)) && "Objective-C declspec doesn't have nullability" ) ? static_cast<void> (0) : __assert_fail ("((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes() & DQ_PR_nullability)) && \"Objective-C declspec doesn't have nullability\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 864, __PRETTY_FUNCTION__)); |
865 | return static_cast<NullabilityKind>(Nullability); |
866 | } |
867 | |
868 | SourceLocation getNullabilityLoc() const { |
869 | assert(((getObjCDeclQualifier() & DQ_CSNullability) ||((((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes () & DQ_PR_nullability)) && "Objective-C declspec doesn't have nullability" ) ? static_cast<void> (0) : __assert_fail ("((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes() & DQ_PR_nullability)) && \"Objective-C declspec doesn't have nullability\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 871, __PRETTY_FUNCTION__)) |
870 | (getPropertyAttributes() & DQ_PR_nullability)) &&((((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes () & DQ_PR_nullability)) && "Objective-C declspec doesn't have nullability" ) ? static_cast<void> (0) : __assert_fail ("((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes() & DQ_PR_nullability)) && \"Objective-C declspec doesn't have nullability\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 871, __PRETTY_FUNCTION__)) |
871 | "Objective-C declspec doesn't have nullability")((((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes () & DQ_PR_nullability)) && "Objective-C declspec doesn't have nullability" ) ? static_cast<void> (0) : __assert_fail ("((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes() & DQ_PR_nullability)) && \"Objective-C declspec doesn't have nullability\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 871, __PRETTY_FUNCTION__)); |
872 | return NullabilityLoc; |
873 | } |
874 | |
875 | void setNullability(SourceLocation loc, NullabilityKind kind) { |
876 | assert(((getObjCDeclQualifier() & DQ_CSNullability) ||((((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes () & DQ_PR_nullability)) && "Set the nullability declspec or property attribute first" ) ? static_cast<void> (0) : __assert_fail ("((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes() & DQ_PR_nullability)) && \"Set the nullability declspec or property attribute first\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 878, __PRETTY_FUNCTION__)) |
877 | (getPropertyAttributes() & DQ_PR_nullability)) &&((((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes () & DQ_PR_nullability)) && "Set the nullability declspec or property attribute first" ) ? static_cast<void> (0) : __assert_fail ("((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes() & DQ_PR_nullability)) && \"Set the nullability declspec or property attribute first\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 878, __PRETTY_FUNCTION__)) |
878 | "Set the nullability declspec or property attribute first")((((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes () & DQ_PR_nullability)) && "Set the nullability declspec or property attribute first" ) ? static_cast<void> (0) : __assert_fail ("((getObjCDeclQualifier() & DQ_CSNullability) || (getPropertyAttributes() & DQ_PR_nullability)) && \"Set the nullability declspec or property attribute first\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 878, __PRETTY_FUNCTION__)); |
879 | Nullability = static_cast<unsigned>(kind); |
880 | NullabilityLoc = loc; |
881 | } |
882 | |
883 | const IdentifierInfo *getGetterName() const { return GetterName; } |
884 | IdentifierInfo *getGetterName() { return GetterName; } |
885 | SourceLocation getGetterNameLoc() const { return GetterNameLoc; } |
886 | void setGetterName(IdentifierInfo *name, SourceLocation loc) { |
887 | GetterName = name; |
888 | GetterNameLoc = loc; |
889 | } |
890 | |
891 | const IdentifierInfo *getSetterName() const { return SetterName; } |
892 | IdentifierInfo *getSetterName() { return SetterName; } |
893 | SourceLocation getSetterNameLoc() const { return SetterNameLoc; } |
894 | void setSetterName(IdentifierInfo *name, SourceLocation loc) { |
895 | SetterName = name; |
896 | SetterNameLoc = loc; |
897 | } |
898 | |
899 | private: |
900 | // FIXME: These two are unrelated and mutually exclusive. So perhaps |
901 | // we can put them in a union to reflect their mutual exclusivity |
902 | // (space saving is negligible). |
903 | unsigned objcDeclQualifier : 7; |
904 | |
905 | // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind |
906 | unsigned PropertyAttributes : 15; |
907 | |
908 | unsigned Nullability : 2; |
909 | |
910 | SourceLocation NullabilityLoc; |
911 | |
912 | IdentifierInfo *GetterName; // getter name or NULL if no getter |
913 | IdentifierInfo *SetterName; // setter name or NULL if no setter |
914 | SourceLocation GetterNameLoc; // location of the getter attribute's value |
915 | SourceLocation SetterNameLoc; // location of the setter attribute's value |
916 | |
917 | }; |
918 | |
919 | /// Describes the kind of unqualified-id parsed. |
920 | enum class UnqualifiedIdKind { |
921 | /// An identifier. |
922 | IK_Identifier, |
923 | /// An overloaded operator name, e.g., operator+. |
924 | IK_OperatorFunctionId, |
925 | /// A conversion function name, e.g., operator int. |
926 | IK_ConversionFunctionId, |
927 | /// A user-defined literal name, e.g., operator "" _i. |
928 | IK_LiteralOperatorId, |
929 | /// A constructor name. |
930 | IK_ConstructorName, |
931 | /// A constructor named via a template-id. |
932 | IK_ConstructorTemplateId, |
933 | /// A destructor name. |
934 | IK_DestructorName, |
935 | /// A template-id, e.g., f<int>. |
936 | IK_TemplateId, |
937 | /// An implicit 'self' parameter |
938 | IK_ImplicitSelfParam, |
939 | /// A deduction-guide name (a template-name) |
940 | IK_DeductionGuideName |
941 | }; |
942 | |
943 | /// Represents a C++ unqualified-id that has been parsed. |
944 | class UnqualifiedId { |
945 | private: |
946 | UnqualifiedId(const UnqualifiedId &Other) = delete; |
947 | const UnqualifiedId &operator=(const UnqualifiedId &) = delete; |
948 | |
949 | public: |
950 | /// Describes the kind of unqualified-id parsed. |
951 | UnqualifiedIdKind Kind; |
952 | |
953 | struct OFI { |
954 | /// The kind of overloaded operator. |
955 | OverloadedOperatorKind Operator; |
956 | |
957 | /// The source locations of the individual tokens that name |
958 | /// the operator, e.g., the "new", "[", and "]" tokens in |
959 | /// operator new []. |
960 | /// |
961 | /// Different operators have different numbers of tokens in their name, |
962 | /// up to three. Any remaining source locations in this array will be |
963 | /// set to an invalid value for operators with fewer than three tokens. |
964 | unsigned SymbolLocations[3]; |
965 | }; |
966 | |
967 | /// Anonymous union that holds extra data associated with the |
968 | /// parsed unqualified-id. |
969 | union { |
970 | /// When Kind == IK_Identifier, the parsed identifier, or when |
971 | /// Kind == IK_UserLiteralId, the identifier suffix. |
972 | IdentifierInfo *Identifier; |
973 | |
974 | /// When Kind == IK_OperatorFunctionId, the overloaded operator |
975 | /// that we parsed. |
976 | struct OFI OperatorFunctionId; |
977 | |
978 | /// When Kind == IK_ConversionFunctionId, the type that the |
979 | /// conversion function names. |
980 | UnionParsedType ConversionFunctionId; |
981 | |
982 | /// When Kind == IK_ConstructorName, the class-name of the type |
983 | /// whose constructor is being referenced. |
984 | UnionParsedType ConstructorName; |
985 | |
986 | /// When Kind == IK_DestructorName, the type referred to by the |
987 | /// class-name. |
988 | UnionParsedType DestructorName; |
989 | |
990 | /// When Kind == IK_DeductionGuideName, the parsed template-name. |
991 | UnionParsedTemplateTy TemplateName; |
992 | |
993 | /// When Kind == IK_TemplateId or IK_ConstructorTemplateId, |
994 | /// the template-id annotation that contains the template name and |
995 | /// template arguments. |
996 | TemplateIdAnnotation *TemplateId; |
997 | }; |
998 | |
999 | /// The location of the first token that describes this unqualified-id, |
1000 | /// which will be the location of the identifier, "operator" keyword, |
1001 | /// tilde (for a destructor), or the template name of a template-id. |
1002 | SourceLocation StartLocation; |
1003 | |
1004 | /// The location of the last token that describes this unqualified-id. |
1005 | SourceLocation EndLocation; |
1006 | |
1007 | UnqualifiedId() |
1008 | : Kind(UnqualifiedIdKind::IK_Identifier), Identifier(nullptr) {} |
1009 | |
1010 | /// Clear out this unqualified-id, setting it to default (invalid) |
1011 | /// state. |
1012 | void clear() { |
1013 | Kind = UnqualifiedIdKind::IK_Identifier; |
1014 | Identifier = nullptr; |
1015 | StartLocation = SourceLocation(); |
1016 | EndLocation = SourceLocation(); |
1017 | } |
1018 | |
1019 | /// Determine whether this unqualified-id refers to a valid name. |
1020 | bool isValid() const { return StartLocation.isValid(); } |
1021 | |
1022 | /// Determine whether this unqualified-id refers to an invalid name. |
1023 | bool isInvalid() const { return !isValid(); } |
1024 | |
1025 | /// Determine what kind of name we have. |
1026 | UnqualifiedIdKind getKind() const { return Kind; } |
1027 | void setKind(UnqualifiedIdKind kind) { Kind = kind; } |
1028 | |
1029 | /// Specify that this unqualified-id was parsed as an identifier. |
1030 | /// |
1031 | /// \param Id the parsed identifier. |
1032 | /// \param IdLoc the location of the parsed identifier. |
1033 | void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc) { |
1034 | Kind = UnqualifiedIdKind::IK_Identifier; |
1035 | Identifier = const_cast<IdentifierInfo *>(Id); |
1036 | StartLocation = EndLocation = IdLoc; |
1037 | } |
1038 | |
1039 | /// Specify that this unqualified-id was parsed as an |
1040 | /// operator-function-id. |
1041 | /// |
1042 | /// \param OperatorLoc the location of the 'operator' keyword. |
1043 | /// |
1044 | /// \param Op the overloaded operator. |
1045 | /// |
1046 | /// \param SymbolLocations the locations of the individual operator symbols |
1047 | /// in the operator. |
1048 | void setOperatorFunctionId(SourceLocation OperatorLoc, |
1049 | OverloadedOperatorKind Op, |
1050 | SourceLocation SymbolLocations[3]); |
1051 | |
1052 | /// Specify that this unqualified-id was parsed as a |
1053 | /// conversion-function-id. |
1054 | /// |
1055 | /// \param OperatorLoc the location of the 'operator' keyword. |
1056 | /// |
1057 | /// \param Ty the type to which this conversion function is converting. |
1058 | /// |
1059 | /// \param EndLoc the location of the last token that makes up the type name. |
1060 | void setConversionFunctionId(SourceLocation OperatorLoc, |
1061 | ParsedType Ty, |
1062 | SourceLocation EndLoc) { |
1063 | Kind = UnqualifiedIdKind::IK_ConversionFunctionId; |
1064 | StartLocation = OperatorLoc; |
1065 | EndLocation = EndLoc; |
1066 | ConversionFunctionId = Ty; |
1067 | } |
1068 | |
1069 | /// Specific that this unqualified-id was parsed as a |
1070 | /// literal-operator-id. |
1071 | /// |
1072 | /// \param Id the parsed identifier. |
1073 | /// |
1074 | /// \param OpLoc the location of the 'operator' keyword. |
1075 | /// |
1076 | /// \param IdLoc the location of the identifier. |
1077 | void setLiteralOperatorId(const IdentifierInfo *Id, SourceLocation OpLoc, |
1078 | SourceLocation IdLoc) { |
1079 | Kind = UnqualifiedIdKind::IK_LiteralOperatorId; |
1080 | Identifier = const_cast<IdentifierInfo *>(Id); |
1081 | StartLocation = OpLoc; |
1082 | EndLocation = IdLoc; |
1083 | } |
1084 | |
1085 | /// Specify that this unqualified-id was parsed as a constructor name. |
1086 | /// |
1087 | /// \param ClassType the class type referred to by the constructor name. |
1088 | /// |
1089 | /// \param ClassNameLoc the location of the class name. |
1090 | /// |
1091 | /// \param EndLoc the location of the last token that makes up the type name. |
1092 | void setConstructorName(ParsedType ClassType, |
1093 | SourceLocation ClassNameLoc, |
1094 | SourceLocation EndLoc) { |
1095 | Kind = UnqualifiedIdKind::IK_ConstructorName; |
1096 | StartLocation = ClassNameLoc; |
1097 | EndLocation = EndLoc; |
1098 | ConstructorName = ClassType; |
1099 | } |
1100 | |
1101 | /// Specify that this unqualified-id was parsed as a |
1102 | /// template-id that names a constructor. |
1103 | /// |
1104 | /// \param TemplateId the template-id annotation that describes the parsed |
1105 | /// template-id. This UnqualifiedId instance will take ownership of the |
1106 | /// \p TemplateId and will free it on destruction. |
1107 | void setConstructorTemplateId(TemplateIdAnnotation *TemplateId); |
1108 | |
1109 | /// Specify that this unqualified-id was parsed as a destructor name. |
1110 | /// |
1111 | /// \param TildeLoc the location of the '~' that introduces the destructor |
1112 | /// name. |
1113 | /// |
1114 | /// \param ClassType the name of the class referred to by the destructor name. |
1115 | void setDestructorName(SourceLocation TildeLoc, |
1116 | ParsedType ClassType, |
1117 | SourceLocation EndLoc) { |
1118 | Kind = UnqualifiedIdKind::IK_DestructorName; |
1119 | StartLocation = TildeLoc; |
1120 | EndLocation = EndLoc; |
1121 | DestructorName = ClassType; |
1122 | } |
1123 | |
1124 | /// Specify that this unqualified-id was parsed as a template-id. |
1125 | /// |
1126 | /// \param TemplateId the template-id annotation that describes the parsed |
1127 | /// template-id. This UnqualifiedId instance will take ownership of the |
1128 | /// \p TemplateId and will free it on destruction. |
1129 | void setTemplateId(TemplateIdAnnotation *TemplateId); |
1130 | |
1131 | /// Specify that this unqualified-id was parsed as a template-name for |
1132 | /// a deduction-guide. |
1133 | /// |
1134 | /// \param Template The parsed template-name. |
1135 | /// \param TemplateLoc The location of the parsed template-name. |
1136 | void setDeductionGuideName(ParsedTemplateTy Template, |
1137 | SourceLocation TemplateLoc) { |
1138 | Kind = UnqualifiedIdKind::IK_DeductionGuideName; |
1139 | TemplateName = Template; |
1140 | StartLocation = EndLocation = TemplateLoc; |
1141 | } |
1142 | |
1143 | /// Return the source range that covers this unqualified-id. |
1144 | SourceRange getSourceRange() const LLVM_READONLY__attribute__((__pure__)) { |
1145 | return SourceRange(StartLocation, EndLocation); |
1146 | } |
1147 | SourceLocation getBeginLoc() const LLVM_READONLY__attribute__((__pure__)) { return StartLocation; } |
1148 | SourceLocation getEndLoc() const LLVM_READONLY__attribute__((__pure__)) { return EndLocation; } |
1149 | }; |
1150 | |
1151 | /// A set of tokens that has been cached for later parsing. |
1152 | typedef SmallVector<Token, 4> CachedTokens; |
1153 | |
1154 | /// One instance of this struct is used for each type in a |
1155 | /// declarator that is parsed. |
1156 | /// |
1157 | /// This is intended to be a small value object. |
1158 | struct DeclaratorChunk { |
1159 | enum { |
1160 | Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren, Pipe |
1161 | } Kind; |
1162 | |
1163 | /// Loc - The place where this type was defined. |
1164 | SourceLocation Loc; |
1165 | /// EndLoc - If valid, the place where this chunck ends. |
1166 | SourceLocation EndLoc; |
1167 | |
1168 | SourceRange getSourceRange() const { |
1169 | if (EndLoc.isInvalid()) |
1170 | return SourceRange(Loc, Loc); |
1171 | return SourceRange(Loc, EndLoc); |
1172 | } |
1173 | |
1174 | ParsedAttributesView AttrList; |
1175 | |
1176 | struct PointerTypeInfo { |
1177 | /// The type qualifiers: const/volatile/restrict/unaligned/atomic. |
1178 | unsigned TypeQuals : 5; |
1179 | |
1180 | /// The location of the const-qualifier, if any. |
1181 | unsigned ConstQualLoc; |
1182 | |
1183 | /// The location of the volatile-qualifier, if any. |
1184 | unsigned VolatileQualLoc; |
1185 | |
1186 | /// The location of the restrict-qualifier, if any. |
1187 | unsigned RestrictQualLoc; |
1188 | |
1189 | /// The location of the _Atomic-qualifier, if any. |
1190 | unsigned AtomicQualLoc; |
1191 | |
1192 | /// The location of the __unaligned-qualifier, if any. |
1193 | unsigned UnalignedQualLoc; |
1194 | |
1195 | void destroy() { |
1196 | } |
1197 | }; |
1198 | |
1199 | struct ReferenceTypeInfo { |
1200 | /// The type qualifier: restrict. [GNU] C++ extension |
1201 | bool HasRestrict : 1; |
1202 | /// True if this is an lvalue reference, false if it's an rvalue reference. |
1203 | bool LValueRef : 1; |
1204 | void destroy() { |
1205 | } |
1206 | }; |
1207 | |
1208 | struct ArrayTypeInfo { |
1209 | /// The type qualifiers for the array: |
1210 | /// const/volatile/restrict/__unaligned/_Atomic. |
1211 | unsigned TypeQuals : 5; |
1212 | |
1213 | /// True if this dimension included the 'static' keyword. |
1214 | unsigned hasStatic : 1; |
1215 | |
1216 | /// True if this dimension was [*]. In this case, NumElts is null. |
1217 | unsigned isStar : 1; |
1218 | |
1219 | /// This is the size of the array, or null if [] or [*] was specified. |
1220 | /// Since the parser is multi-purpose, and we don't want to impose a root |
1221 | /// expression class on all clients, NumElts is untyped. |
1222 | Expr *NumElts; |
1223 | |
1224 | void destroy() {} |
1225 | }; |
1226 | |
1227 | /// ParamInfo - An array of paraminfo objects is allocated whenever a function |
1228 | /// declarator is parsed. There are two interesting styles of parameters |
1229 | /// here: |
1230 | /// K&R-style identifier lists and parameter type lists. K&R-style identifier |
1231 | /// lists will have information about the identifier, but no type information. |
1232 | /// Parameter type lists will have type info (if the actions module provides |
1233 | /// it), but may have null identifier info: e.g. for 'void foo(int X, int)'. |
1234 | struct ParamInfo { |
1235 | IdentifierInfo *Ident; |
1236 | SourceLocation IdentLoc; |
1237 | Decl *Param; |
1238 | |
1239 | /// DefaultArgTokens - When the parameter's default argument |
1240 | /// cannot be parsed immediately (because it occurs within the |
1241 | /// declaration of a member function), it will be stored here as a |
1242 | /// sequence of tokens to be parsed once the class definition is |
1243 | /// complete. Non-NULL indicates that there is a default argument. |
1244 | std::unique_ptr<CachedTokens> DefaultArgTokens; |
1245 | |
1246 | ParamInfo() = default; |
1247 | ParamInfo(IdentifierInfo *ident, SourceLocation iloc, |
1248 | Decl *param, |
1249 | std::unique_ptr<CachedTokens> DefArgTokens = nullptr) |
1250 | : Ident(ident), IdentLoc(iloc), Param(param), |
1251 | DefaultArgTokens(std::move(DefArgTokens)) {} |
1252 | }; |
1253 | |
1254 | struct TypeAndRange { |
1255 | ParsedType Ty; |
1256 | SourceRange Range; |
1257 | }; |
1258 | |
1259 | struct FunctionTypeInfo { |
1260 | /// hasPrototype - This is true if the function had at least one typed |
1261 | /// parameter. If the function is () or (a,b,c), then it has no prototype, |
1262 | /// and is treated as a K&R-style function. |
1263 | unsigned hasPrototype : 1; |
1264 | |
1265 | /// isVariadic - If this function has a prototype, and if that |
1266 | /// proto ends with ',...)', this is true. When true, EllipsisLoc |
1267 | /// contains the location of the ellipsis. |
1268 | unsigned isVariadic : 1; |
1269 | |
1270 | /// Can this declaration be a constructor-style initializer? |
1271 | unsigned isAmbiguous : 1; |
1272 | |
1273 | /// Whether the ref-qualifier (if any) is an lvalue reference. |
1274 | /// Otherwise, it's an rvalue reference. |
1275 | unsigned RefQualifierIsLValueRef : 1; |
1276 | |
1277 | /// ExceptionSpecType - An ExceptionSpecificationType value. |
1278 | unsigned ExceptionSpecType : 4; |
1279 | |
1280 | /// DeleteParams - If this is true, we need to delete[] Params. |
1281 | unsigned DeleteParams : 1; |
1282 | |
1283 | /// HasTrailingReturnType - If this is true, a trailing return type was |
1284 | /// specified. |
1285 | unsigned HasTrailingReturnType : 1; |
1286 | |
1287 | /// The location of the left parenthesis in the source. |
1288 | unsigned LParenLoc; |
1289 | |
1290 | /// When isVariadic is true, the location of the ellipsis in the source. |
1291 | unsigned EllipsisLoc; |
1292 | |
1293 | /// The location of the right parenthesis in the source. |
1294 | unsigned RParenLoc; |
1295 | |
1296 | /// NumParams - This is the number of formal parameters specified by the |
1297 | /// declarator. |
1298 | unsigned NumParams; |
1299 | |
1300 | /// NumExceptionsOrDecls - This is the number of types in the |
1301 | /// dynamic-exception-decl, if the function has one. In C, this is the |
1302 | /// number of declarations in the function prototype. |
1303 | unsigned NumExceptionsOrDecls; |
1304 | |
1305 | /// The location of the ref-qualifier, if any. |
1306 | /// |
1307 | /// If this is an invalid location, there is no ref-qualifier. |
1308 | unsigned RefQualifierLoc; |
1309 | |
1310 | /// The location of the 'mutable' qualifer in a lambda-declarator, if |
1311 | /// any. |
1312 | unsigned MutableLoc; |
1313 | |
1314 | /// The beginning location of the exception specification, if any. |
1315 | unsigned ExceptionSpecLocBeg; |
1316 | |
1317 | /// The end location of the exception specification, if any. |
1318 | unsigned ExceptionSpecLocEnd; |
1319 | |
1320 | /// Params - This is a pointer to a new[]'d array of ParamInfo objects that |
1321 | /// describe the parameters specified by this function declarator. null if |
1322 | /// there are no parameters specified. |
1323 | ParamInfo *Params; |
1324 | |
1325 | /// DeclSpec for the function with the qualifier related info. |
1326 | DeclSpec *MethodQualifiers; |
1327 | |
1328 | /// AtttibuteFactory for the MethodQualifiers. |
1329 | AttributeFactory *QualAttrFactory; |
1330 | |
1331 | union { |
1332 | /// Pointer to a new[]'d array of TypeAndRange objects that |
1333 | /// contain the types in the function's dynamic exception specification |
1334 | /// and their locations, if there is one. |
1335 | TypeAndRange *Exceptions; |
1336 | |
1337 | /// Pointer to the expression in the noexcept-specifier of this |
1338 | /// function, if it has one. |
1339 | Expr *NoexceptExpr; |
1340 | |
1341 | /// Pointer to the cached tokens for an exception-specification |
1342 | /// that has not yet been parsed. |
1343 | CachedTokens *ExceptionSpecTokens; |
1344 | |
1345 | /// Pointer to a new[]'d array of declarations that need to be available |
1346 | /// for lookup inside the function body, if one exists. Does not exist in |
1347 | /// C++. |
1348 | NamedDecl **DeclsInPrototype; |
1349 | }; |
1350 | |
1351 | /// If HasTrailingReturnType is true, this is the trailing return |
1352 | /// type specified. |
1353 | UnionParsedType TrailingReturnType; |
1354 | |
1355 | /// Reset the parameter list to having zero parameters. |
1356 | /// |
1357 | /// This is used in various places for error recovery. |
1358 | void freeParams() { |
1359 | for (unsigned I = 0; I < NumParams; ++I) |
1360 | Params[I].DefaultArgTokens.reset(); |
1361 | if (DeleteParams) { |
1362 | delete[] Params; |
1363 | DeleteParams = false; |
1364 | } |
1365 | NumParams = 0; |
1366 | } |
1367 | |
1368 | void destroy() { |
1369 | freeParams(); |
1370 | delete QualAttrFactory; |
1371 | delete MethodQualifiers; |
1372 | switch (getExceptionSpecType()) { |
1373 | default: |
1374 | break; |
1375 | case EST_Dynamic: |
1376 | delete[] Exceptions; |
1377 | break; |
1378 | case EST_Unparsed: |
1379 | delete ExceptionSpecTokens; |
1380 | break; |
1381 | case EST_None: |
1382 | if (NumExceptionsOrDecls != 0) |
1383 | delete[] DeclsInPrototype; |
1384 | break; |
1385 | } |
1386 | } |
1387 | |
1388 | DeclSpec &getOrCreateMethodQualifiers() { |
1389 | if (!MethodQualifiers) { |
1390 | QualAttrFactory = new AttributeFactory(); |
1391 | MethodQualifiers = new DeclSpec(*QualAttrFactory); |
1392 | } |
1393 | return *MethodQualifiers; |
1394 | } |
1395 | |
1396 | /// isKNRPrototype - Return true if this is a K&R style identifier list, |
1397 | /// like "void foo(a,b,c)". In a function definition, this will be followed |
1398 | /// by the parameter type definitions. |
1399 | bool isKNRPrototype() const { return !hasPrototype && NumParams != 0; } |
1400 | |
1401 | SourceLocation getLParenLoc() const { |
1402 | return SourceLocation::getFromRawEncoding(LParenLoc); |
1403 | } |
1404 | |
1405 | SourceLocation getEllipsisLoc() const { |
1406 | return SourceLocation::getFromRawEncoding(EllipsisLoc); |
1407 | } |
1408 | |
1409 | SourceLocation getRParenLoc() const { |
1410 | return SourceLocation::getFromRawEncoding(RParenLoc); |
1411 | } |
1412 | |
1413 | SourceLocation getExceptionSpecLocBeg() const { |
1414 | return SourceLocation::getFromRawEncoding(ExceptionSpecLocBeg); |
1415 | } |
1416 | |
1417 | SourceLocation getExceptionSpecLocEnd() const { |
1418 | return SourceLocation::getFromRawEncoding(ExceptionSpecLocEnd); |
1419 | } |
1420 | |
1421 | SourceRange getExceptionSpecRange() const { |
1422 | return SourceRange(getExceptionSpecLocBeg(), getExceptionSpecLocEnd()); |
1423 | } |
1424 | |
1425 | /// Retrieve the location of the ref-qualifier, if any. |
1426 | SourceLocation getRefQualifierLoc() const { |
1427 | return SourceLocation::getFromRawEncoding(RefQualifierLoc); |
1428 | } |
1429 | |
1430 | /// Retrieve the location of the 'const' qualifier. |
1431 | SourceLocation getConstQualifierLoc() const { |
1432 | assert(MethodQualifiers)((MethodQualifiers) ? static_cast<void> (0) : __assert_fail ("MethodQualifiers", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 1432, __PRETTY_FUNCTION__)); |
1433 | return MethodQualifiers->getConstSpecLoc(); |
1434 | } |
1435 | |
1436 | /// Retrieve the location of the 'volatile' qualifier. |
1437 | SourceLocation getVolatileQualifierLoc() const { |
1438 | assert(MethodQualifiers)((MethodQualifiers) ? static_cast<void> (0) : __assert_fail ("MethodQualifiers", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 1438, __PRETTY_FUNCTION__)); |
1439 | return MethodQualifiers->getVolatileSpecLoc(); |
1440 | } |
1441 | |
1442 | /// Retrieve the location of the 'restrict' qualifier. |
1443 | SourceLocation getRestrictQualifierLoc() const { |
1444 | assert(MethodQualifiers)((MethodQualifiers) ? static_cast<void> (0) : __assert_fail ("MethodQualifiers", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 1444, __PRETTY_FUNCTION__)); |
1445 | return MethodQualifiers->getRestrictSpecLoc(); |
1446 | } |
1447 | |
1448 | /// Retrieve the location of the 'mutable' qualifier, if any. |
1449 | SourceLocation getMutableLoc() const { |
1450 | return SourceLocation::getFromRawEncoding(MutableLoc); |
1451 | } |
1452 | |
1453 | /// Determine whether this function declaration contains a |
1454 | /// ref-qualifier. |
1455 | bool hasRefQualifier() const { return getRefQualifierLoc().isValid(); } |
1456 | |
1457 | /// Determine whether this lambda-declarator contains a 'mutable' |
1458 | /// qualifier. |
1459 | bool hasMutableQualifier() const { return getMutableLoc().isValid(); } |
1460 | |
1461 | /// Determine whether this method has qualifiers. |
1462 | bool hasMethodTypeQualifiers() const { |
1463 | return MethodQualifiers && (MethodQualifiers->getTypeQualifiers() || |
1464 | MethodQualifiers->getAttributes().size()); |
1465 | } |
1466 | |
1467 | /// Get the type of exception specification this function has. |
1468 | ExceptionSpecificationType getExceptionSpecType() const { |
1469 | return static_cast<ExceptionSpecificationType>(ExceptionSpecType); |
1470 | } |
1471 | |
1472 | /// Get the number of dynamic exception specifications. |
1473 | unsigned getNumExceptions() const { |
1474 | assert(ExceptionSpecType != EST_None)((ExceptionSpecType != EST_None) ? static_cast<void> (0 ) : __assert_fail ("ExceptionSpecType != EST_None", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 1474, __PRETTY_FUNCTION__)); |
1475 | return NumExceptionsOrDecls; |
1476 | } |
1477 | |
1478 | /// Get the non-parameter decls defined within this function |
1479 | /// prototype. Typically these are tag declarations. |
1480 | ArrayRef<NamedDecl *> getDeclsInPrototype() const { |
1481 | assert(ExceptionSpecType == EST_None)((ExceptionSpecType == EST_None) ? static_cast<void> (0 ) : __assert_fail ("ExceptionSpecType == EST_None", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 1481, __PRETTY_FUNCTION__)); |
1482 | return llvm::makeArrayRef(DeclsInPrototype, NumExceptionsOrDecls); |
1483 | } |
1484 | |
1485 | /// Determine whether this function declarator had a |
1486 | /// trailing-return-type. |
1487 | bool hasTrailingReturnType() const { return HasTrailingReturnType; } |
1488 | |
1489 | /// Get the trailing-return-type for this function declarator. |
1490 | ParsedType getTrailingReturnType() const { return TrailingReturnType; } |
1491 | }; |
1492 | |
1493 | struct BlockPointerTypeInfo { |
1494 | /// For now, sema will catch these as invalid. |
1495 | /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic. |
1496 | unsigned TypeQuals : 5; |
1497 | |
1498 | void destroy() { |
1499 | } |
1500 | }; |
1501 | |
1502 | struct MemberPointerTypeInfo { |
1503 | /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic. |
1504 | unsigned TypeQuals : 5; |
1505 | // CXXScopeSpec has a constructor, so it can't be a direct member. |
1506 | // So we need some pointer-aligned storage and a bit of trickery. |
1507 | alignas(CXXScopeSpec) char ScopeMem[sizeof(CXXScopeSpec)]; |
1508 | CXXScopeSpec &Scope() { |
1509 | return *reinterpret_cast<CXXScopeSpec *>(ScopeMem); |
1510 | } |
1511 | const CXXScopeSpec &Scope() const { |
1512 | return *reinterpret_cast<const CXXScopeSpec *>(ScopeMem); |
1513 | } |
1514 | void destroy() { |
1515 | Scope().~CXXScopeSpec(); |
1516 | } |
1517 | }; |
1518 | |
1519 | struct PipeTypeInfo { |
1520 | /// The access writes. |
1521 | unsigned AccessWrites : 3; |
1522 | |
1523 | void destroy() {} |
1524 | }; |
1525 | |
1526 | union { |
1527 | PointerTypeInfo Ptr; |
1528 | ReferenceTypeInfo Ref; |
1529 | ArrayTypeInfo Arr; |
1530 | FunctionTypeInfo Fun; |
1531 | BlockPointerTypeInfo Cls; |
1532 | MemberPointerTypeInfo Mem; |
1533 | PipeTypeInfo PipeInfo; |
1534 | }; |
1535 | |
1536 | void destroy() { |
1537 | switch (Kind) { |
1538 | case DeclaratorChunk::Function: return Fun.destroy(); |
1539 | case DeclaratorChunk::Pointer: return Ptr.destroy(); |
1540 | case DeclaratorChunk::BlockPointer: return Cls.destroy(); |
1541 | case DeclaratorChunk::Reference: return Ref.destroy(); |
1542 | case DeclaratorChunk::Array: return Arr.destroy(); |
1543 | case DeclaratorChunk::MemberPointer: return Mem.destroy(); |
1544 | case DeclaratorChunk::Paren: return; |
1545 | case DeclaratorChunk::Pipe: return PipeInfo.destroy(); |
1546 | } |
1547 | } |
1548 | |
1549 | /// If there are attributes applied to this declaratorchunk, return |
1550 | /// them. |
1551 | const ParsedAttributesView &getAttrs() const { return AttrList; } |
1552 | ParsedAttributesView &getAttrs() { return AttrList; } |
1553 | |
1554 | /// Return a DeclaratorChunk for a pointer. |
1555 | static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, |
1556 | SourceLocation ConstQualLoc, |
1557 | SourceLocation VolatileQualLoc, |
1558 | SourceLocation RestrictQualLoc, |
1559 | SourceLocation AtomicQualLoc, |
1560 | SourceLocation UnalignedQualLoc) { |
1561 | DeclaratorChunk I; |
1562 | I.Kind = Pointer; |
1563 | I.Loc = Loc; |
1564 | I.Ptr.TypeQuals = TypeQuals; |
1565 | I.Ptr.ConstQualLoc = ConstQualLoc.getRawEncoding(); |
1566 | I.Ptr.VolatileQualLoc = VolatileQualLoc.getRawEncoding(); |
1567 | I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding(); |
1568 | I.Ptr.AtomicQualLoc = AtomicQualLoc.getRawEncoding(); |
1569 | I.Ptr.UnalignedQualLoc = UnalignedQualLoc.getRawEncoding(); |
1570 | return I; |
1571 | } |
1572 | |
1573 | /// Return a DeclaratorChunk for a reference. |
1574 | static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc, |
1575 | bool lvalue) { |
1576 | DeclaratorChunk I; |
1577 | I.Kind = Reference; |
1578 | I.Loc = Loc; |
1579 | I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0; |
1580 | I.Ref.LValueRef = lvalue; |
1581 | return I; |
1582 | } |
1583 | |
1584 | /// Return a DeclaratorChunk for an array. |
1585 | static DeclaratorChunk getArray(unsigned TypeQuals, |
1586 | bool isStatic, bool isStar, Expr *NumElts, |
1587 | SourceLocation LBLoc, SourceLocation RBLoc) { |
1588 | DeclaratorChunk I; |
1589 | I.Kind = Array; |
1590 | I.Loc = LBLoc; |
1591 | I.EndLoc = RBLoc; |
1592 | I.Arr.TypeQuals = TypeQuals; |
1593 | I.Arr.hasStatic = isStatic; |
1594 | I.Arr.isStar = isStar; |
1595 | I.Arr.NumElts = NumElts; |
1596 | return I; |
1597 | } |
1598 | |
1599 | /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. |
1600 | /// "TheDeclarator" is the declarator that this will be added to. |
1601 | static DeclaratorChunk getFunction(bool HasProto, |
1602 | bool IsAmbiguous, |
1603 | SourceLocation LParenLoc, |
1604 | ParamInfo *Params, unsigned NumParams, |
1605 | SourceLocation EllipsisLoc, |
1606 | SourceLocation RParenLoc, |
1607 | bool RefQualifierIsLvalueRef, |
1608 | SourceLocation RefQualifierLoc, |
1609 | SourceLocation MutableLoc, |
1610 | ExceptionSpecificationType ESpecType, |
1611 | SourceRange ESpecRange, |
1612 | ParsedType *Exceptions, |
1613 | SourceRange *ExceptionRanges, |
1614 | unsigned NumExceptions, |
1615 | Expr *NoexceptExpr, |
1616 | CachedTokens *ExceptionSpecTokens, |
1617 | ArrayRef<NamedDecl *> DeclsInPrototype, |
1618 | SourceLocation LocalRangeBegin, |
1619 | SourceLocation LocalRangeEnd, |
1620 | Declarator &TheDeclarator, |
1621 | TypeResult TrailingReturnType = |
1622 | TypeResult(), |
1623 | DeclSpec *MethodQualifiers = nullptr); |
1624 | |
1625 | /// Return a DeclaratorChunk for a block. |
1626 | static DeclaratorChunk getBlockPointer(unsigned TypeQuals, |
1627 | SourceLocation Loc) { |
1628 | DeclaratorChunk I; |
1629 | I.Kind = BlockPointer; |
1630 | I.Loc = Loc; |
1631 | I.Cls.TypeQuals = TypeQuals; |
1632 | return I; |
1633 | } |
1634 | |
1635 | /// Return a DeclaratorChunk for a block. |
1636 | static DeclaratorChunk getPipe(unsigned TypeQuals, |
1637 | SourceLocation Loc) { |
1638 | DeclaratorChunk I; |
1639 | I.Kind = Pipe; |
1640 | I.Loc = Loc; |
1641 | I.Cls.TypeQuals = TypeQuals; |
1642 | return I; |
1643 | } |
1644 | |
1645 | static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS, |
1646 | unsigned TypeQuals, |
1647 | SourceLocation Loc) { |
1648 | DeclaratorChunk I; |
1649 | I.Kind = MemberPointer; |
1650 | I.Loc = SS.getBeginLoc(); |
1651 | I.EndLoc = Loc; |
1652 | I.Mem.TypeQuals = TypeQuals; |
1653 | new (I.Mem.ScopeMem) CXXScopeSpec(SS); |
1654 | return I; |
1655 | } |
1656 | |
1657 | /// Return a DeclaratorChunk for a paren. |
1658 | static DeclaratorChunk getParen(SourceLocation LParenLoc, |
1659 | SourceLocation RParenLoc) { |
1660 | DeclaratorChunk I; |
1661 | I.Kind = Paren; |
1662 | I.Loc = LParenLoc; |
1663 | I.EndLoc = RParenLoc; |
1664 | return I; |
1665 | } |
1666 | |
1667 | bool isParen() const { |
1668 | return Kind == Paren; |
1669 | } |
1670 | }; |
1671 | |
1672 | /// A parsed C++17 decomposition declarator of the form |
1673 | /// '[' identifier-list ']' |
1674 | class DecompositionDeclarator { |
1675 | public: |
1676 | struct Binding { |
1677 | IdentifierInfo *Name; |
1678 | SourceLocation NameLoc; |
1679 | }; |
1680 | |
1681 | private: |
1682 | /// The locations of the '[' and ']' tokens. |
1683 | SourceLocation LSquareLoc, RSquareLoc; |
1684 | |
1685 | /// The bindings. |
1686 | Binding *Bindings; |
1687 | unsigned NumBindings : 31; |
1688 | unsigned DeleteBindings : 1; |
1689 | |
1690 | friend class Declarator; |
1691 | |
1692 | public: |
1693 | DecompositionDeclarator() |
1694 | : Bindings(nullptr), NumBindings(0), DeleteBindings(false) {} |
1695 | DecompositionDeclarator(const DecompositionDeclarator &G) = delete; |
1696 | DecompositionDeclarator &operator=(const DecompositionDeclarator &G) = delete; |
1697 | ~DecompositionDeclarator() { |
1698 | if (DeleteBindings) |
1699 | delete[] Bindings; |
1700 | } |
1701 | |
1702 | void clear() { |
1703 | LSquareLoc = RSquareLoc = SourceLocation(); |
1704 | if (DeleteBindings) |
1705 | delete[] Bindings; |
1706 | Bindings = nullptr; |
1707 | NumBindings = 0; |
1708 | DeleteBindings = false; |
1709 | } |
1710 | |
1711 | ArrayRef<Binding> bindings() const { |
1712 | return llvm::makeArrayRef(Bindings, NumBindings); |
1713 | } |
1714 | |
1715 | bool isSet() const { return LSquareLoc.isValid(); } |
1716 | |
1717 | SourceLocation getLSquareLoc() const { return LSquareLoc; } |
1718 | SourceLocation getRSquareLoc() const { return RSquareLoc; } |
1719 | SourceRange getSourceRange() const { |
1720 | return SourceRange(LSquareLoc, RSquareLoc); |
1721 | } |
1722 | }; |
1723 | |
1724 | /// Described the kind of function definition (if any) provided for |
1725 | /// a function. |
1726 | enum FunctionDefinitionKind { |
1727 | FDK_Declaration, |
1728 | FDK_Definition, |
1729 | FDK_Defaulted, |
1730 | FDK_Deleted |
1731 | }; |
1732 | |
1733 | enum class DeclaratorContext { |
1734 | FileContext, // File scope declaration. |
1735 | PrototypeContext, // Within a function prototype. |
1736 | ObjCResultContext, // An ObjC method result type. |
1737 | ObjCParameterContext,// An ObjC method parameter type. |
1738 | KNRTypeListContext, // K&R type definition list for formals. |
1739 | TypeNameContext, // Abstract declarator for types. |
1740 | FunctionalCastContext, // Type in a C++ functional cast expression. |
1741 | MemberContext, // Struct/Union field. |
1742 | BlockContext, // Declaration within a block in a function. |
1743 | ForContext, // Declaration within first part of a for loop. |
1744 | InitStmtContext, // Declaration within optional init stmt of if/switch. |
1745 | ConditionContext, // Condition declaration in a C++ if/switch/while/for. |
1746 | TemplateParamContext,// Within a template parameter list. |
1747 | CXXNewContext, // C++ new-expression. |
1748 | CXXCatchContext, // C++ catch exception-declaration |
1749 | ObjCCatchContext, // Objective-C catch exception-declaration |
1750 | BlockLiteralContext, // Block literal declarator. |
1751 | LambdaExprContext, // Lambda-expression declarator. |
1752 | LambdaExprParameterContext, // Lambda-expression parameter declarator. |
1753 | ConversionIdContext, // C++ conversion-type-id. |
1754 | TrailingReturnContext, // C++11 trailing-type-specifier. |
1755 | TrailingReturnVarContext, // C++11 trailing-type-specifier for variable. |
1756 | TemplateArgContext, // Any template argument (in template argument list). |
1757 | TemplateTypeArgContext, // Template type argument (in default argument). |
1758 | AliasDeclContext, // C++11 alias-declaration. |
1759 | AliasTemplateContext // C++11 alias-declaration template. |
1760 | }; |
1761 | |
1762 | |
1763 | /// Information about one declarator, including the parsed type |
1764 | /// information and the identifier. |
1765 | /// |
1766 | /// When the declarator is fully formed, this is turned into the appropriate |
1767 | /// Decl object. |
1768 | /// |
1769 | /// Declarators come in two types: normal declarators and abstract declarators. |
1770 | /// Abstract declarators are used when parsing types, and don't have an |
1771 | /// identifier. Normal declarators do have ID's. |
1772 | /// |
1773 | /// Instances of this class should be a transient object that lives on the |
1774 | /// stack, not objects that are allocated in large quantities on the heap. |
1775 | class Declarator { |
1776 | |
1777 | private: |
1778 | const DeclSpec &DS; |
1779 | CXXScopeSpec SS; |
1780 | UnqualifiedId Name; |
1781 | SourceRange Range; |
1782 | |
1783 | /// Where we are parsing this declarator. |
1784 | DeclaratorContext Context; |
1785 | |
1786 | /// The C++17 structured binding, if any. This is an alternative to a Name. |
1787 | DecompositionDeclarator BindingGroup; |
1788 | |
1789 | /// DeclTypeInfo - This holds each type that the declarator includes as it is |
1790 | /// parsed. This is pushed from the identifier out, which means that element |
1791 | /// #0 will be the most closely bound to the identifier, and |
1792 | /// DeclTypeInfo.back() will be the least closely bound. |
1793 | SmallVector<DeclaratorChunk, 8> DeclTypeInfo; |
1794 | |
1795 | /// InvalidType - Set by Sema::GetTypeForDeclarator(). |
1796 | unsigned InvalidType : 1; |
1797 | |
1798 | /// GroupingParens - Set by Parser::ParseParenDeclarator(). |
1799 | unsigned GroupingParens : 1; |
1800 | |
1801 | /// FunctionDefinition - Is this Declarator for a function or member |
1802 | /// definition and, if so, what kind? |
1803 | /// |
1804 | /// Actually a FunctionDefinitionKind. |
1805 | unsigned FunctionDefinition : 2; |
1806 | |
1807 | /// Is this Declarator a redeclaration? |
1808 | unsigned Redeclaration : 1; |
1809 | |
1810 | /// true if the declaration is preceded by \c __extension__. |
1811 | unsigned Extension : 1; |
1812 | |
1813 | /// Indicates whether this is an Objective-C instance variable. |
1814 | unsigned ObjCIvar : 1; |
1815 | |
1816 | /// Indicates whether this is an Objective-C 'weak' property. |
1817 | unsigned ObjCWeakProperty : 1; |
1818 | |
1819 | /// Indicates whether the InlineParams / InlineBindings storage has been used. |
1820 | unsigned InlineStorageUsed : 1; |
1821 | |
1822 | /// Attrs - Attributes. |
1823 | ParsedAttributes Attrs; |
1824 | |
1825 | /// The asm label, if specified. |
1826 | Expr *AsmLabel; |
1827 | |
1828 | #ifndef _MSC_VER |
1829 | union { |
1830 | #endif |
1831 | /// InlineParams - This is a local array used for the first function decl |
1832 | /// chunk to avoid going to the heap for the common case when we have one |
1833 | /// function chunk in the declarator. |
1834 | DeclaratorChunk::ParamInfo InlineParams[16]; |
1835 | DecompositionDeclarator::Binding InlineBindings[16]; |
1836 | #ifndef _MSC_VER |
1837 | }; |
1838 | #endif |
1839 | |
1840 | /// If this is the second or subsequent declarator in this declaration, |
1841 | /// the location of the comma before this declarator. |
1842 | SourceLocation CommaLoc; |
1843 | |
1844 | /// If provided, the source location of the ellipsis used to describe |
1845 | /// this declarator as a parameter pack. |
1846 | SourceLocation EllipsisLoc; |
1847 | |
1848 | friend struct DeclaratorChunk; |
1849 | |
1850 | public: |
1851 | Declarator(const DeclSpec &ds, DeclaratorContext C) |
1852 | : DS(ds), Range(ds.getSourceRange()), Context(C), |
1853 | InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error), |
1854 | GroupingParens(false), FunctionDefinition(FDK_Declaration), |
1855 | Redeclaration(false), Extension(false), ObjCIvar(false), |
1856 | ObjCWeakProperty(false), InlineStorageUsed(false), |
1857 | Attrs(ds.getAttributePool().getFactory()), AsmLabel(nullptr) {} |
1858 | |
1859 | ~Declarator() { |
1860 | clear(); |
1861 | } |
1862 | /// getDeclSpec - Return the declaration-specifier that this declarator was |
1863 | /// declared with. |
1864 | const DeclSpec &getDeclSpec() const { return DS; } |
1865 | |
1866 | /// getMutableDeclSpec - Return a non-const version of the DeclSpec. This |
1867 | /// should be used with extreme care: declspecs can often be shared between |
1868 | /// multiple declarators, so mutating the DeclSpec affects all of the |
1869 | /// Declarators. This should only be done when the declspec is known to not |
1870 | /// be shared or when in error recovery etc. |
1871 | DeclSpec &getMutableDeclSpec() { return const_cast<DeclSpec &>(DS); } |
1872 | |
1873 | AttributePool &getAttributePool() const { |
1874 | return Attrs.getPool(); |
1875 | } |
1876 | |
1877 | /// getCXXScopeSpec - Return the C++ scope specifier (global scope or |
1878 | /// nested-name-specifier) that is part of the declarator-id. |
1879 | const CXXScopeSpec &getCXXScopeSpec() const { return SS; } |
1880 | CXXScopeSpec &getCXXScopeSpec() { return SS; } |
1881 | |
1882 | /// Retrieve the name specified by this declarator. |
1883 | UnqualifiedId &getName() { return Name; } |
1884 | |
1885 | const DecompositionDeclarator &getDecompositionDeclarator() const { |
1886 | return BindingGroup; |
1887 | } |
1888 | |
1889 | DeclaratorContext getContext() const { return Context; } |
1890 | |
1891 | bool isPrototypeContext() const { |
1892 | return (Context == DeclaratorContext::PrototypeContext || |
1893 | Context == DeclaratorContext::ObjCParameterContext || |
1894 | Context == DeclaratorContext::ObjCResultContext || |
1895 | Context == DeclaratorContext::LambdaExprParameterContext); |
1896 | } |
1897 | |
1898 | /// Get the source range that spans this declarator. |
1899 | SourceRange getSourceRange() const LLVM_READONLY__attribute__((__pure__)) { return Range; } |
1900 | SourceLocation getBeginLoc() const LLVM_READONLY__attribute__((__pure__)) { return Range.getBegin(); } |
1901 | SourceLocation getEndLoc() const LLVM_READONLY__attribute__((__pure__)) { return Range.getEnd(); } |
1902 | |
1903 | void SetSourceRange(SourceRange R) { Range = R; } |
1904 | /// SetRangeBegin - Set the start of the source range to Loc, unless it's |
1905 | /// invalid. |
1906 | void SetRangeBegin(SourceLocation Loc) { |
1907 | if (!Loc.isInvalid()) |
1908 | Range.setBegin(Loc); |
1909 | } |
1910 | /// SetRangeEnd - Set the end of the source range to Loc, unless it's invalid. |
1911 | void SetRangeEnd(SourceLocation Loc) { |
1912 | if (!Loc.isInvalid()) |
1913 | Range.setEnd(Loc); |
1914 | } |
1915 | /// ExtendWithDeclSpec - Extend the declarator source range to include the |
1916 | /// given declspec, unless its location is invalid. Adopts the range start if |
1917 | /// the current range start is invalid. |
1918 | void ExtendWithDeclSpec(const DeclSpec &DS) { |
1919 | SourceRange SR = DS.getSourceRange(); |
1920 | if (Range.getBegin().isInvalid()) |
1921 | Range.setBegin(SR.getBegin()); |
1922 | if (!SR.getEnd().isInvalid()) |
1923 | Range.setEnd(SR.getEnd()); |
1924 | } |
1925 | |
1926 | /// Reset the contents of this Declarator. |
1927 | void clear() { |
1928 | SS.clear(); |
1929 | Name.clear(); |
1930 | Range = DS.getSourceRange(); |
1931 | BindingGroup.clear(); |
1932 | |
1933 | for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i) |
1934 | DeclTypeInfo[i].destroy(); |
1935 | DeclTypeInfo.clear(); |
1936 | Attrs.clear(); |
1937 | AsmLabel = nullptr; |
1938 | InlineStorageUsed = false; |
1939 | ObjCIvar = false; |
1940 | ObjCWeakProperty = false; |
1941 | CommaLoc = SourceLocation(); |
1942 | EllipsisLoc = SourceLocation(); |
1943 | } |
1944 | |
1945 | /// mayOmitIdentifier - Return true if the identifier is either optional or |
1946 | /// not allowed. This is true for typenames, prototypes, and template |
1947 | /// parameter lists. |
1948 | bool mayOmitIdentifier() const { |
1949 | switch (Context) { |
1950 | case DeclaratorContext::FileContext: |
1951 | case DeclaratorContext::KNRTypeListContext: |
1952 | case DeclaratorContext::MemberContext: |
1953 | case DeclaratorContext::BlockContext: |
1954 | case DeclaratorContext::ForContext: |
1955 | case DeclaratorContext::InitStmtContext: |
1956 | case DeclaratorContext::ConditionContext: |
1957 | return false; |
1958 | |
1959 | case DeclaratorContext::TypeNameContext: |
1960 | case DeclaratorContext::FunctionalCastContext: |
1961 | case DeclaratorContext::AliasDeclContext: |
1962 | case DeclaratorContext::AliasTemplateContext: |
1963 | case DeclaratorContext::PrototypeContext: |
1964 | case DeclaratorContext::LambdaExprParameterContext: |
1965 | case DeclaratorContext::ObjCParameterContext: |
1966 | case DeclaratorContext::ObjCResultContext: |
1967 | case DeclaratorContext::TemplateParamContext: |
1968 | case DeclaratorContext::CXXNewContext: |
1969 | case DeclaratorContext::CXXCatchContext: |
1970 | case DeclaratorContext::ObjCCatchContext: |
1971 | case DeclaratorContext::BlockLiteralContext: |
1972 | case DeclaratorContext::LambdaExprContext: |
1973 | case DeclaratorContext::ConversionIdContext: |
1974 | case DeclaratorContext::TemplateArgContext: |
1975 | case DeclaratorContext::TemplateTypeArgContext: |
1976 | case DeclaratorContext::TrailingReturnContext: |
1977 | case DeclaratorContext::TrailingReturnVarContext: |
1978 | return true; |
1979 | } |
1980 | llvm_unreachable("unknown context kind!")::llvm::llvm_unreachable_internal("unknown context kind!", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 1980); |
1981 | } |
1982 | |
1983 | /// mayHaveIdentifier - Return true if the identifier is either optional or |
1984 | /// required. This is true for normal declarators and prototypes, but not |
1985 | /// typenames. |
1986 | bool mayHaveIdentifier() const { |
1987 | switch (Context) { |
1988 | case DeclaratorContext::FileContext: |
1989 | case DeclaratorContext::KNRTypeListContext: |
1990 | case DeclaratorContext::MemberContext: |
1991 | case DeclaratorContext::BlockContext: |
1992 | case DeclaratorContext::ForContext: |
1993 | case DeclaratorContext::InitStmtContext: |
1994 | case DeclaratorContext::ConditionContext: |
1995 | case DeclaratorContext::PrototypeContext: |
1996 | case DeclaratorContext::LambdaExprParameterContext: |
1997 | case DeclaratorContext::TemplateParamContext: |
1998 | case DeclaratorContext::CXXCatchContext: |
1999 | case DeclaratorContext::ObjCCatchContext: |
2000 | return true; |
2001 | |
2002 | case DeclaratorContext::TypeNameContext: |
2003 | case DeclaratorContext::FunctionalCastContext: |
2004 | case DeclaratorContext::CXXNewContext: |
2005 | case DeclaratorContext::AliasDeclContext: |
2006 | case DeclaratorContext::AliasTemplateContext: |
2007 | case DeclaratorContext::ObjCParameterContext: |
2008 | case DeclaratorContext::ObjCResultContext: |
2009 | case DeclaratorContext::BlockLiteralContext: |
2010 | case DeclaratorContext::LambdaExprContext: |
2011 | case DeclaratorContext::ConversionIdContext: |
2012 | case DeclaratorContext::TemplateArgContext: |
2013 | case DeclaratorContext::TemplateTypeArgContext: |
2014 | case DeclaratorContext::TrailingReturnContext: |
2015 | case DeclaratorContext::TrailingReturnVarContext: |
2016 | return false; |
2017 | } |
2018 | llvm_unreachable("unknown context kind!")::llvm::llvm_unreachable_internal("unknown context kind!", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 2018); |
2019 | } |
2020 | |
2021 | /// Return true if the context permits a C++17 decomposition declarator. |
2022 | bool mayHaveDecompositionDeclarator() const { |
2023 | switch (Context) { |
2024 | case DeclaratorContext::FileContext: |
2025 | // FIXME: It's not clear that the proposal meant to allow file-scope |
2026 | // structured bindings, but it does. |
2027 | case DeclaratorContext::BlockContext: |
2028 | case DeclaratorContext::ForContext: |
2029 | case DeclaratorContext::InitStmtContext: |
2030 | case DeclaratorContext::ConditionContext: |
2031 | return true; |
2032 | |
2033 | case DeclaratorContext::MemberContext: |
2034 | case DeclaratorContext::PrototypeContext: |
2035 | case DeclaratorContext::TemplateParamContext: |
2036 | // Maybe one day... |
2037 | return false; |
2038 | |
2039 | // These contexts don't allow any kind of non-abstract declarator. |
2040 | case DeclaratorContext::KNRTypeListContext: |
2041 | case DeclaratorContext::TypeNameContext: |
2042 | case DeclaratorContext::FunctionalCastContext: |
2043 | case DeclaratorContext::AliasDeclContext: |
2044 | case DeclaratorContext::AliasTemplateContext: |
2045 | case DeclaratorContext::LambdaExprParameterContext: |
2046 | case DeclaratorContext::ObjCParameterContext: |
2047 | case DeclaratorContext::ObjCResultContext: |
2048 | case DeclaratorContext::CXXNewContext: |
2049 | case DeclaratorContext::CXXCatchContext: |
2050 | case DeclaratorContext::ObjCCatchContext: |
2051 | case DeclaratorContext::BlockLiteralContext: |
2052 | case DeclaratorContext::LambdaExprContext: |
2053 | case DeclaratorContext::ConversionIdContext: |
2054 | case DeclaratorContext::TemplateArgContext: |
2055 | case DeclaratorContext::TemplateTypeArgContext: |
2056 | case DeclaratorContext::TrailingReturnContext: |
2057 | case DeclaratorContext::TrailingReturnVarContext: |
2058 | return false; |
2059 | } |
2060 | llvm_unreachable("unknown context kind!")::llvm::llvm_unreachable_internal("unknown context kind!", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 2060); |
2061 | } |
2062 | |
2063 | /// mayBeFollowedByCXXDirectInit - Return true if the declarator can be |
2064 | /// followed by a C++ direct initializer, e.g. "int x(1);". |
2065 | bool mayBeFollowedByCXXDirectInit() const { |
2066 | if (hasGroupingParens()) return false; |
2067 | |
2068 | if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) |
2069 | return false; |
2070 | |
2071 | if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern && |
2072 | Context != DeclaratorContext::FileContext) |
2073 | return false; |
2074 | |
2075 | // Special names can't have direct initializers. |
2076 | if (Name.getKind() != UnqualifiedIdKind::IK_Identifier) |
2077 | return false; |
2078 | |
2079 | switch (Context) { |
2080 | case DeclaratorContext::FileContext: |
2081 | case DeclaratorContext::BlockContext: |
2082 | case DeclaratorContext::ForContext: |
2083 | case DeclaratorContext::InitStmtContext: |
2084 | case DeclaratorContext::TrailingReturnVarContext: |
2085 | return true; |
2086 | |
2087 | case DeclaratorContext::ConditionContext: |
2088 | // This may not be followed by a direct initializer, but it can't be a |
2089 | // function declaration either, and we'd prefer to perform a tentative |
2090 | // parse in order to produce the right diagnostic. |
2091 | return true; |
2092 | |
2093 | case DeclaratorContext::KNRTypeListContext: |
2094 | case DeclaratorContext::MemberContext: |
2095 | case DeclaratorContext::PrototypeContext: |
2096 | case DeclaratorContext::LambdaExprParameterContext: |
2097 | case DeclaratorContext::ObjCParameterContext: |
2098 | case DeclaratorContext::ObjCResultContext: |
2099 | case DeclaratorContext::TemplateParamContext: |
2100 | case DeclaratorContext::CXXCatchContext: |
2101 | case DeclaratorContext::ObjCCatchContext: |
2102 | case DeclaratorContext::TypeNameContext: |
2103 | case DeclaratorContext::FunctionalCastContext: // FIXME |
2104 | case DeclaratorContext::CXXNewContext: |
2105 | case DeclaratorContext::AliasDeclContext: |
2106 | case DeclaratorContext::AliasTemplateContext: |
2107 | case DeclaratorContext::BlockLiteralContext: |
2108 | case DeclaratorContext::LambdaExprContext: |
2109 | case DeclaratorContext::ConversionIdContext: |
2110 | case DeclaratorContext::TemplateArgContext: |
2111 | case DeclaratorContext::TemplateTypeArgContext: |
2112 | case DeclaratorContext::TrailingReturnContext: |
2113 | return false; |
2114 | } |
2115 | llvm_unreachable("unknown context kind!")::llvm::llvm_unreachable_internal("unknown context kind!", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 2115); |
2116 | } |
2117 | |
2118 | /// isPastIdentifier - Return true if we have parsed beyond the point where |
2119 | /// the name would appear. (This may happen even if we haven't actually parsed |
2120 | /// a name, perhaps because this context doesn't require one.) |
2121 | bool isPastIdentifier() const { return Name.isValid(); } |
2122 | |
2123 | /// hasName - Whether this declarator has a name, which might be an |
2124 | /// identifier (accessible via getIdentifier()) or some kind of |
2125 | /// special C++ name (constructor, destructor, etc.), or a structured |
2126 | /// binding (which is not exactly a name, but occupies the same position). |
2127 | bool hasName() const { |
2128 | return Name.getKind() != UnqualifiedIdKind::IK_Identifier || |
2129 | Name.Identifier || isDecompositionDeclarator(); |
2130 | } |
2131 | |
2132 | /// Return whether this declarator is a decomposition declarator. |
2133 | bool isDecompositionDeclarator() const { |
2134 | return BindingGroup.isSet(); |
2135 | } |
2136 | |
2137 | IdentifierInfo *getIdentifier() const { |
2138 | if (Name.getKind() == UnqualifiedIdKind::IK_Identifier) |
2139 | return Name.Identifier; |
2140 | |
2141 | return nullptr; |
2142 | } |
2143 | SourceLocation getIdentifierLoc() const { return Name.StartLocation; } |
2144 | |
2145 | /// Set the name of this declarator to be the given identifier. |
2146 | void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) { |
2147 | Name.setIdentifier(Id, IdLoc); |
2148 | } |
2149 | |
2150 | /// Set the decomposition bindings for this declarator. |
2151 | void |
2152 | setDecompositionBindings(SourceLocation LSquareLoc, |
2153 | ArrayRef<DecompositionDeclarator::Binding> Bindings, |
2154 | SourceLocation RSquareLoc); |
2155 | |
2156 | /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to |
2157 | /// EndLoc, which should be the last token of the chunk. |
2158 | /// This function takes attrs by R-Value reference because it takes ownership |
2159 | /// of those attributes from the parameter. |
2160 | void AddTypeInfo(const DeclaratorChunk &TI, ParsedAttributes &&attrs, |
2161 | SourceLocation EndLoc) { |
2162 | DeclTypeInfo.push_back(TI); |
2163 | DeclTypeInfo.back().getAttrs().addAll(attrs.begin(), attrs.end()); |
2164 | getAttributePool().takeAllFrom(attrs.getPool()); |
2165 | |
2166 | if (!EndLoc.isInvalid()) |
2167 | SetRangeEnd(EndLoc); |
2168 | } |
2169 | |
2170 | /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to |
2171 | /// EndLoc, which should be the last token of the chunk. |
2172 | void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) { |
2173 | DeclTypeInfo.push_back(TI); |
2174 | |
2175 | if (!EndLoc.isInvalid()) |
2176 | SetRangeEnd(EndLoc); |
2177 | } |
2178 | |
2179 | /// Add a new innermost chunk to this declarator. |
2180 | void AddInnermostTypeInfo(const DeclaratorChunk &TI) { |
2181 | DeclTypeInfo.insert(DeclTypeInfo.begin(), TI); |
2182 | } |
2183 | |
2184 | /// Return the number of types applied to this declarator. |
2185 | unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); } |
2186 | |
2187 | /// Return the specified TypeInfo from this declarator. TypeInfo #0 is |
2188 | /// closest to the identifier. |
2189 | const DeclaratorChunk &getTypeObject(unsigned i) const { |
2190 | assert(i < DeclTypeInfo.size() && "Invalid type chunk")((i < DeclTypeInfo.size() && "Invalid type chunk") ? static_cast<void> (0) : __assert_fail ("i < DeclTypeInfo.size() && \"Invalid type chunk\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 2190, __PRETTY_FUNCTION__)); |
2191 | return DeclTypeInfo[i]; |
2192 | } |
2193 | DeclaratorChunk &getTypeObject(unsigned i) { |
2194 | assert(i < DeclTypeInfo.size() && "Invalid type chunk")((i < DeclTypeInfo.size() && "Invalid type chunk") ? static_cast<void> (0) : __assert_fail ("i < DeclTypeInfo.size() && \"Invalid type chunk\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 2194, __PRETTY_FUNCTION__)); |
2195 | return DeclTypeInfo[i]; |
2196 | } |
2197 | |
2198 | typedef SmallVectorImpl<DeclaratorChunk>::const_iterator type_object_iterator; |
2199 | typedef llvm::iterator_range<type_object_iterator> type_object_range; |
2200 | |
2201 | /// Returns the range of type objects, from the identifier outwards. |
2202 | type_object_range type_objects() const { |
2203 | return type_object_range(DeclTypeInfo.begin(), DeclTypeInfo.end()); |
2204 | } |
2205 | |
2206 | void DropFirstTypeObject() { |
2207 | assert(!DeclTypeInfo.empty() && "No type chunks to drop.")((!DeclTypeInfo.empty() && "No type chunks to drop.") ? static_cast<void> (0) : __assert_fail ("!DeclTypeInfo.empty() && \"No type chunks to drop.\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 2207, __PRETTY_FUNCTION__)); |
2208 | DeclTypeInfo.front().destroy(); |
2209 | DeclTypeInfo.erase(DeclTypeInfo.begin()); |
2210 | } |
2211 | |
2212 | /// Return the innermost (closest to the declarator) chunk of this |
2213 | /// declarator that is not a parens chunk, or null if there are no |
2214 | /// non-parens chunks. |
2215 | const DeclaratorChunk *getInnermostNonParenChunk() const { |
2216 | for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) { |
2217 | if (!DeclTypeInfo[i].isParen()) |
2218 | return &DeclTypeInfo[i]; |
2219 | } |
2220 | return nullptr; |
2221 | } |
2222 | |
2223 | /// Return the outermost (furthest from the declarator) chunk of |
2224 | /// this declarator that is not a parens chunk, or null if there are |
2225 | /// no non-parens chunks. |
2226 | const DeclaratorChunk *getOutermostNonParenChunk() const { |
2227 | for (unsigned i = DeclTypeInfo.size(), i_end = 0; i != i_end; --i) { |
2228 | if (!DeclTypeInfo[i-1].isParen()) |
2229 | return &DeclTypeInfo[i-1]; |
2230 | } |
2231 | return nullptr; |
2232 | } |
2233 | |
2234 | /// isArrayOfUnknownBound - This method returns true if the declarator |
2235 | /// is a declarator for an array of unknown bound (looking through |
2236 | /// parentheses). |
2237 | bool isArrayOfUnknownBound() const { |
2238 | const DeclaratorChunk *chunk = getInnermostNonParenChunk(); |
2239 | return (chunk && chunk->Kind == DeclaratorChunk::Array && |
2240 | !chunk->Arr.NumElts); |
2241 | } |
2242 | |
2243 | /// isFunctionDeclarator - This method returns true if the declarator |
2244 | /// is a function declarator (looking through parentheses). |
2245 | /// If true is returned, then the reference type parameter idx is |
2246 | /// assigned with the index of the declaration chunk. |
2247 | bool isFunctionDeclarator(unsigned& idx) const { |
2248 | for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) { |
2249 | switch (DeclTypeInfo[i].Kind) { |
2250 | case DeclaratorChunk::Function: |
2251 | idx = i; |
2252 | return true; |
2253 | case DeclaratorChunk::Paren: |
2254 | continue; |
2255 | case DeclaratorChunk::Pointer: |
2256 | case DeclaratorChunk::Reference: |
2257 | case DeclaratorChunk::Array: |
2258 | case DeclaratorChunk::BlockPointer: |
2259 | case DeclaratorChunk::MemberPointer: |
2260 | case DeclaratorChunk::Pipe: |
2261 | return false; |
2262 | } |
2263 | llvm_unreachable("Invalid type chunk")::llvm::llvm_unreachable_internal("Invalid type chunk", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 2263); |
2264 | } |
2265 | return false; |
2266 | } |
2267 | |
2268 | /// isFunctionDeclarator - Once this declarator is fully parsed and formed, |
2269 | /// this method returns true if the identifier is a function declarator |
2270 | /// (looking through parentheses). |
2271 | bool isFunctionDeclarator() const { |
2272 | unsigned index; |
2273 | return isFunctionDeclarator(index); |
2274 | } |
2275 | |
2276 | /// getFunctionTypeInfo - Retrieves the function type info object |
2277 | /// (looking through parentheses). |
2278 | DeclaratorChunk::FunctionTypeInfo &getFunctionTypeInfo() { |
2279 | assert(isFunctionDeclarator() && "Not a function declarator!")((isFunctionDeclarator() && "Not a function declarator!" ) ? static_cast<void> (0) : __assert_fail ("isFunctionDeclarator() && \"Not a function declarator!\"" , "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 2279, __PRETTY_FUNCTION__)); |
2280 | unsigned index = 0; |
2281 | isFunctionDeclarator(index); |
2282 | return DeclTypeInfo[index].Fun; |
2283 | } |
2284 | |
2285 | /// getFunctionTypeInfo - Retrieves the function type info object |
2286 | /// (looking through parentheses). |
2287 | const DeclaratorChunk::FunctionTypeInfo &getFunctionTypeInfo() const { |
2288 | return const_cast<Declarator*>(this)->getFunctionTypeInfo(); |
2289 | } |
2290 | |
2291 | /// Determine whether the declaration that will be produced from |
2292 | /// this declaration will be a function. |
2293 | /// |
2294 | /// A declaration can declare a function even if the declarator itself |
2295 | /// isn't a function declarator, if the type specifier refers to a function |
2296 | /// type. This routine checks for both cases. |
2297 | bool isDeclarationOfFunction() const; |
2298 | |
2299 | /// Return true if this declaration appears in a context where a |
2300 | /// function declarator would be a function declaration. |
2301 | bool isFunctionDeclarationContext() const { |
2302 | if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) |
2303 | return false; |
2304 | |
2305 | switch (Context) { |
2306 | case DeclaratorContext::FileContext: |
2307 | case DeclaratorContext::MemberContext: |
2308 | case DeclaratorContext::BlockContext: |
2309 | case DeclaratorContext::ForContext: |
2310 | case DeclaratorContext::InitStmtContext: |
2311 | return true; |
2312 | |
2313 | case DeclaratorContext::ConditionContext: |
2314 | case DeclaratorContext::KNRTypeListContext: |
2315 | case DeclaratorContext::TypeNameContext: |
2316 | case DeclaratorContext::FunctionalCastContext: |
2317 | case DeclaratorContext::AliasDeclContext: |
2318 | case DeclaratorContext::AliasTemplateContext: |
2319 | case DeclaratorContext::PrototypeContext: |
2320 | case DeclaratorContext::LambdaExprParameterContext: |
2321 | case DeclaratorContext::ObjCParameterContext: |
2322 | case DeclaratorContext::ObjCResultContext: |
2323 | case DeclaratorContext::TemplateParamContext: |
2324 | case DeclaratorContext::CXXNewContext: |
2325 | case DeclaratorContext::CXXCatchContext: |
2326 | case DeclaratorContext::ObjCCatchContext: |
2327 | case DeclaratorContext::BlockLiteralContext: |
2328 | case DeclaratorContext::LambdaExprContext: |
2329 | case DeclaratorContext::ConversionIdContext: |
2330 | case DeclaratorContext::TemplateArgContext: |
2331 | case DeclaratorContext::TemplateTypeArgContext: |
2332 | case DeclaratorContext::TrailingReturnContext: |
2333 | case DeclaratorContext::TrailingReturnVarContext: |
2334 | return false; |
2335 | } |
2336 | llvm_unreachable("unknown context kind!")::llvm::llvm_unreachable_internal("unknown context kind!", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 2336); |
2337 | } |
2338 | |
2339 | /// Determine whether this declaration appears in a context where an |
2340 | /// expression could appear. |
2341 | bool isExpressionContext() const { |
2342 | switch (Context) { |
2343 | case DeclaratorContext::FileContext: |
2344 | case DeclaratorContext::KNRTypeListContext: |
2345 | case DeclaratorContext::MemberContext: |
2346 | |
2347 | // FIXME: sizeof(...) permits an expression. |
2348 | case DeclaratorContext::TypeNameContext: |
2349 | |
2350 | case DeclaratorContext::FunctionalCastContext: |
2351 | case DeclaratorContext::AliasDeclContext: |
2352 | case DeclaratorContext::AliasTemplateContext: |
2353 | case DeclaratorContext::PrototypeContext: |
2354 | case DeclaratorContext::LambdaExprParameterContext: |
2355 | case DeclaratorContext::ObjCParameterContext: |
2356 | case DeclaratorContext::ObjCResultContext: |
2357 | case DeclaratorContext::TemplateParamContext: |
2358 | case DeclaratorContext::CXXNewContext: |
2359 | case DeclaratorContext::CXXCatchContext: |
2360 | case DeclaratorContext::ObjCCatchContext: |
2361 | case DeclaratorContext::BlockLiteralContext: |
2362 | case DeclaratorContext::LambdaExprContext: |
2363 | case DeclaratorContext::ConversionIdContext: |
2364 | case DeclaratorContext::TrailingReturnContext: |
2365 | case DeclaratorContext::TrailingReturnVarContext: |
2366 | case DeclaratorContext::TemplateTypeArgContext: |
2367 | return false; |
2368 | |
2369 | case DeclaratorContext::BlockContext: |
2370 | case DeclaratorContext::ForContext: |
2371 | case DeclaratorContext::InitStmtContext: |
2372 | case DeclaratorContext::ConditionContext: |
2373 | case DeclaratorContext::TemplateArgContext: |
2374 | return true; |
2375 | } |
2376 | |
2377 | llvm_unreachable("unknown context kind!")::llvm::llvm_unreachable_internal("unknown context kind!", "/build/llvm-toolchain-snapshot-10~svn373517/tools/clang/include/clang/Sema/DeclSpec.h" , 2377); |
2378 | } |
2379 | |
2380 | /// Return true if a function declarator at this position would be a |
2381 | /// function declaration. |
2382 | bool isFunctionDeclaratorAFunctionDeclaration() const { |
2383 | if (!isFunctionDeclarationContext()) |
2384 | return false; |
2385 | |
2386 | for (unsigned I = 0, N = getNumTypeObjects(); I != N; ++I) |
2387 | if (getTypeObject(I).Kind != DeclaratorChunk::Paren) |
2388 | return false; |
2389 | |
2390 | return true; |
2391 | } |
2392 | |
2393 | /// Determine whether a trailing return type was written (at any |
2394 | /// level) within this declarator. |
2395 | bool hasTrailingReturnType() const { |
2396 | for (const auto &Chunk : type_objects()) |
2397 | if (Chunk.Kind == DeclaratorChunk::Function && |
2398 | Chunk.Fun.hasTrailingReturnType()) |
2399 | return true; |
2400 | return false; |
2401 | } |
2402 | |
2403 | /// takeAttributes - Takes attributes from the given parsed-attributes |
2404 | /// set and add them to this declarator. |
2405 | /// |
2406 | /// These examples both add 3 attributes to "var": |
2407 | /// short int var __attribute__((aligned(16),common,deprecated)); |
2408 | /// short int x, __attribute__((aligned(16)) var |
2409 | /// __attribute__((common,deprecated)); |
2410 | /// |
2411 | /// Also extends the range of the declarator. |
2412 | void takeAttributes(ParsedAttributes &attrs, SourceLocation lastLoc) { |
2413 | Attrs.takeAllFrom(attrs); |
2414 | |
2415 | if (!lastLoc.isInvalid()) |
2416 | SetRangeEnd(lastLoc); |
2417 | } |
2418 | |
2419 | const ParsedAttributes &getAttributes() const { return Attrs; } |
2420 | ParsedAttributes &getAttributes() { return Attrs; } |
2421 | |
2422 | /// hasAttributes - do we contain any attributes? |
2423 | bool hasAttributes() const { |
2424 | if (!getAttributes().empty() || getDeclSpec().hasAttributes()) |
2425 | return true; |
2426 | for (unsigned i = 0, e = getNumTypeObjects(); i != e; ++i) |
2427 | if (!getTypeObject(i).getAttrs().empty()) |
2428 | return true; |
2429 | return false; |
2430 | } |
2431 | |
2432 | /// Return a source range list of C++11 attributes associated |
2433 | /// with the declarator. |
2434 | void getCXX11AttributeRanges(SmallVectorImpl<SourceRange> &Ranges) { |
2435 | for (const ParsedAttr &AL : Attrs) |
2436 | if (AL.isCXX11Attribute()) |
2437 | Ranges.push_back(AL.getRange()); |
2438 | } |
2439 | |
2440 | void setAsmLabel(Expr *E) { AsmLabel = E; } |
2441 | Expr *getAsmLabel() const { return AsmLabel; } |
2442 | |
2443 | void setExtension(bool Val = true) { Extension = Val; } |
2444 | bool getExtension() const { return Extension; } |
2445 | |
2446 | void setObjCIvar(bool Val = true) { ObjCIvar = Val; } |
2447 | bool isObjCIvar() const { return ObjCIvar; } |
2448 | |
2449 | void setObjCWeakProperty(bool Val = true) { ObjCWeakProperty = Val; } |
2450 | bool isObjCWeakProperty() const { return ObjCWeakProperty; } |
2451 | |
2452 | void setInvalidType(bool Val = true) { InvalidType = Val; } |
2453 | bool isInvalidType() const { |
2454 | return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error; |
2455 | } |
2456 | |
2457 | void setGroupingParens(bool flag) { GroupingParens = flag; } |
2458 | bool hasGroupingParens() const { return GroupingParens; } |
2459 | |
2460 | bool isFirstDeclarator() const { return !CommaLoc.isValid(); } |
2461 | SourceLocation getCommaLoc() const { return CommaLoc; } |
2462 | void setCommaLoc(SourceLocation CL) { CommaLoc = CL; } |
2463 | |
2464 | bool hasEllipsis() const { return EllipsisLoc.isValid(); } |
2465 | SourceLocation getEllipsisLoc() const { return EllipsisLoc; } |
2466 | void setEllipsisLoc(SourceLocation EL) { EllipsisLoc = EL; } |
2467 | |
2468 | void setFunctionDefinitionKind(FunctionDefinitionKind Val) { |
2469 | FunctionDefinition = Val; |
2470 | } |
2471 | |
2472 | bool isFunctionDefinition() const { |
2473 | return getFunctionDefinitionKind() != FDK_Declaration; |
2474 | } |
2475 | |
2476 | FunctionDefinitionKind getFunctionDefinitionKind() const { |
2477 | return (FunctionDefinitionKind)FunctionDefinition; |
2478 | } |
2479 | |
2480 | /// Returns true if this declares a real member and not a friend. |
2481 | bool isFirstDeclarationOfMember() { |
2482 | return getContext() == DeclaratorContext::MemberContext && |
2483 | !getDeclSpec().isFriendSpecified(); |
2484 | } |
2485 | |
2486 | /// Returns true if this declares a static member. This cannot be called on a |
2487 | /// declarator outside of a MemberContext because we won't know until |
2488 | /// redeclaration time if the decl is static. |
2489 | bool isStaticMember(); |
2490 | |
2491 | /// Returns true if this declares a constructor or a destructor. |
2492 | bool isCtorOrDtor(); |
2493 | |
2494 | void setRedeclaration(bool Val) { Redeclaration = Val; } |
2495 | bool isRedeclaration() const { return Redeclaration; } |
2496 | }; |
2497 | |
2498 | /// This little struct is used to capture information about |
2499 | /// structure field declarators, which is basically just a bitfield size. |
2500 | struct FieldDeclarator { |
2501 | Declarator D; |
2502 | Expr *BitfieldSize; |
2503 | explicit FieldDeclarator(const DeclSpec &DS) |
2504 | : D(DS, DeclaratorContext::MemberContext), |
2505 | BitfieldSize(nullptr) {} |
2506 | }; |
2507 | |
2508 | /// Represents a C++11 virt-specifier-seq. |
2509 | class VirtSpecifiers { |
2510 | public: |
2511 | enum Specifier { |
2512 | VS_None = 0, |
2513 | VS_Override = 1, |
2514 | VS_Final = 2, |
2515 | VS_Sealed = 4, |
2516 | // Represents the __final keyword, which is legal for gcc in pre-C++11 mode. |
2517 | VS_GNU_Final = 8 |
2518 | }; |
2519 | |
2520 | VirtSpecifiers() : Specifiers(0), LastSpecifier(VS_None) { } |
2521 | |
2522 | bool SetSpecifier(Specifier VS, SourceLocation Loc, |
2523 | const char *&PrevSpec); |
2524 | |
2525 | bool isUnset() const { return Specifiers == 0; } |
2526 | |
2527 | bool isOverrideSpecified() const { return Specifiers & VS_Override; } |
2528 | SourceLocation getOverrideLoc() const { return VS_overrideLoc; } |
2529 | |
2530 | bool isFinalSpecified() const { return Specifiers & (VS_Final | VS_Sealed | VS_GNU_Final); } |
2531 | bool isFinalSpelledSealed() const { return Specifiers & VS_Sealed; } |
2532 | SourceLocation getFinalLoc() const { return VS_finalLoc; } |
2533 | |
2534 | void clear() { Specifiers = 0; } |
2535 | |
2536 | static const char *getSpecifierName(Specifier VS); |
2537 | |
2538 | SourceLocation getFirstLocation() const { return FirstLocation; } |
2539 | SourceLocation getLastLocation() const { return LastLocation; } |
2540 | Specifier getLastSpecifier() const { return LastSpecifier; } |
2541 | |
2542 | private: |
2543 | unsigned Specifiers; |
2544 | Specifier LastSpecifier; |
2545 | |
2546 | SourceLocation VS_overrideLoc, VS_finalLoc; |
2547 | SourceLocation FirstLocation; |
2548 | SourceLocation LastLocation; |
2549 | }; |
2550 | |
2551 | enum class LambdaCaptureInitKind { |
2552 | NoInit, //!< [a] |
2553 | CopyInit, //!< [a = b], [a = {b}] |
2554 | DirectInit, //!< [a(b)] |
2555 | ListInit //!< [a{b}] |
2556 | }; |
2557 | |
2558 | /// Represents a complete lambda introducer. |
2559 | struct LambdaIntroducer { |
2560 | /// An individual capture in a lambda introducer. |
2561 | struct LambdaCapture { |
2562 | LambdaCaptureKind Kind; |
2563 | SourceLocation Loc; |
2564 | IdentifierInfo *Id; |
2565 | SourceLocation EllipsisLoc; |
2566 | LambdaCaptureInitKind InitKind; |
2567 | ExprResult Init; |
2568 | ParsedType InitCaptureType; |
2569 | SourceRange ExplicitRange; |
2570 | |
2571 | LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc, |
2572 | IdentifierInfo *Id, SourceLocation EllipsisLoc, |
2573 | LambdaCaptureInitKind InitKind, ExprResult Init, |
2574 | ParsedType InitCaptureType, |
2575 | SourceRange ExplicitRange) |
2576 | : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc), |
2577 | InitKind(InitKind), Init(Init), InitCaptureType(InitCaptureType), |
2578 | ExplicitRange(ExplicitRange) {} |
2579 | }; |
2580 | |
2581 | SourceRange Range; |
2582 | SourceLocation DefaultLoc; |
2583 | LambdaCaptureDefault Default; |
2584 | SmallVector<LambdaCapture, 4> Captures; |
2585 | |
2586 | LambdaIntroducer() |
2587 | : Default(LCD_None) {} |
2588 | |
2589 | /// Append a capture in a lambda introducer. |
2590 | void addCapture(LambdaCaptureKind Kind, |
2591 | SourceLocation Loc, |
2592 | IdentifierInfo* Id, |
2593 | SourceLocation EllipsisLoc, |
2594 | LambdaCaptureInitKind InitKind, |
2595 | ExprResult Init, |
2596 | ParsedType InitCaptureType, |
2597 | SourceRange ExplicitRange) { |
2598 | Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc, InitKind, Init, |
2599 | InitCaptureType, ExplicitRange)); |
2600 | } |
2601 | }; |
2602 | |
2603 | } // end namespace clang |
2604 | |
2605 | #endif // LLVM_CLANG_SEMA_DECLSPEC_H |