1 | //===--- SemaCXXScopeSpec.cpp - Semantic Analysis for C++ scope specifiers-===// |
---|---|
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 C++ semantic analysis for scope specifiers. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "TypeLocBuilder.h" |
14 | #include "clang/AST/ASTContext.h" |
15 | #include "clang/AST/DeclTemplate.h" |
16 | #include "clang/AST/ExprCXX.h" |
17 | #include "clang/AST/NestedNameSpecifier.h" |
18 | #include "clang/Basic/PartialDiagnostic.h" |
19 | #include "clang/Sema/DeclSpec.h" |
20 | #include "clang/Sema/Lookup.h" |
21 | #include "clang/Sema/Template.h" |
22 | #include "llvm/ADT/STLExtras.h" |
23 | using namespace clang; |
24 | |
25 | /// Find the current instantiation that associated with the given type. |
26 | static CXXRecordDecl *getCurrentInstantiationOf(QualType T, |
27 | DeclContext *CurContext) { |
28 | if (T.isNull()) |
29 | return nullptr; |
30 | |
31 | const Type *Ty = T->getCanonicalTypeInternal().getTypePtr(); |
32 | if (const RecordType *RecordTy = dyn_cast<RecordType>(Val: Ty)) { |
33 | CXXRecordDecl *Record = cast<CXXRecordDecl>(Val: RecordTy->getDecl()); |
34 | if (Record->isCurrentInstantiation(CurContext)) |
35 | return Record; |
36 | |
37 | return nullptr; |
38 | } else if (isa<InjectedClassNameType>(Val: Ty)) |
39 | return cast<InjectedClassNameType>(Val: Ty)->getDecl(); |
40 | else |
41 | return nullptr; |
42 | } |
43 | |
44 | DeclContext *Sema::computeDeclContext(QualType T) { |
45 | if (!T->isDependentType()) |
46 | if (const TagType *Tag = T->getAs<TagType>()) |
47 | return Tag->getDecl(); |
48 | |
49 | return ::getCurrentInstantiationOf(T, CurContext); |
50 | } |
51 | |
52 | DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, |
53 | bool EnteringContext) { |
54 | if (!SS.isSet() || SS.isInvalid()) |
55 | return nullptr; |
56 | |
57 | NestedNameSpecifier *NNS = SS.getScopeRep(); |
58 | if (NNS->isDependent()) { |
59 | // If this nested-name-specifier refers to the current |
60 | // instantiation, return its DeclContext. |
61 | if (CXXRecordDecl *Record = getCurrentInstantiationOf(NNS)) |
62 | return Record; |
63 | |
64 | if (EnteringContext) { |
65 | const Type *NNSType = NNS->getAsType(); |
66 | if (!NNSType) { |
67 | return nullptr; |
68 | } |
69 | |
70 | // Look through type alias templates, per C++0x [temp.dep.type]p1. |
71 | NNSType = Context.getCanonicalType(T: NNSType); |
72 | if (const auto *SpecType = |
73 | dyn_cast<TemplateSpecializationType>(Val: NNSType)) { |
74 | // We are entering the context of the nested name specifier, so try to |
75 | // match the nested name specifier to either a primary class template |
76 | // or a class template partial specialization. |
77 | if (ClassTemplateDecl *ClassTemplate = |
78 | dyn_cast_or_null<ClassTemplateDecl>( |
79 | Val: SpecType->getTemplateName().getAsTemplateDecl())) { |
80 | // FIXME: The fallback on the search of partial |
81 | // specialization using ContextType should be eventually removed since |
82 | // it doesn't handle the case of constrained template parameters |
83 | // correctly. Currently removing this fallback would change the |
84 | // diagnostic output for invalid code in a number of tests. |
85 | ClassTemplatePartialSpecializationDecl *PartialSpec = nullptr; |
86 | ArrayRef<TemplateParameterList *> TemplateParamLists = |
87 | SS.getTemplateParamLists(); |
88 | if (!TemplateParamLists.empty()) { |
89 | unsigned Depth = ClassTemplate->getTemplateParameters()->getDepth(); |
90 | auto L = find_if(Range&: TemplateParamLists, |
91 | P: [Depth](TemplateParameterList *TPL) { |
92 | return TPL->getDepth() == Depth; |
93 | }); |
94 | if (L != TemplateParamLists.end()) { |
95 | void *Pos = nullptr; |
96 | PartialSpec = ClassTemplate->findPartialSpecialization( |
97 | Args: SpecType->template_arguments(), TPL: *L, InsertPos&: Pos); |
98 | } |
99 | } else { |
100 | PartialSpec = |
101 | ClassTemplate->findPartialSpecialization(T: QualType(SpecType, 0)); |
102 | } |
103 | |
104 | if (PartialSpec) { |
105 | // A declaration of the partial specialization must be visible. |
106 | // We can always recover here, because this only happens when we're |
107 | // entering the context, and that can't happen in a SFINAE context. |
108 | assert(!isSFINAEContext() && "partial specialization scope " |
109 | "specifier in SFINAE context?"); |
110 | if (PartialSpec->hasDefinition() && |
111 | !hasReachableDefinition(PartialSpec)) |
112 | diagnoseMissingImport(SS.getLastQualifierNameLoc(), PartialSpec, |
113 | MissingImportKind::PartialSpecialization, |
114 | true); |
115 | return PartialSpec; |
116 | } |
117 | |
118 | // If the type of the nested name specifier is the same as the |
119 | // injected class name of the named class template, we're entering |
120 | // into that class template definition. |
121 | QualType Injected = |
122 | ClassTemplate->getInjectedClassNameSpecialization(); |
123 | if (Context.hasSameType(T1: Injected, T2: QualType(SpecType, 0))) |
124 | return ClassTemplate->getTemplatedDecl(); |
125 | } |
126 | } else if (const RecordType *RecordT = NNSType->getAs<RecordType>()) { |
127 | // The nested name specifier refers to a member of a class template. |
128 | return RecordT->getDecl(); |
129 | } |
130 | } |
131 | |
132 | return nullptr; |
133 | } |
134 | |
135 | switch (NNS->getKind()) { |
136 | case NestedNameSpecifier::Identifier: |
137 | llvm_unreachable("Dependent nested-name-specifier has no DeclContext"); |
138 | |
139 | case NestedNameSpecifier::Namespace: |
140 | return NNS->getAsNamespace(); |
141 | |
142 | case NestedNameSpecifier::NamespaceAlias: |
143 | return NNS->getAsNamespaceAlias()->getNamespace(); |
144 | |
145 | case NestedNameSpecifier::TypeSpec: { |
146 | const TagType *Tag = NNS->getAsType()->getAs<TagType>(); |
147 | assert(Tag && "Non-tag type in nested-name-specifier"); |
148 | return Tag->getDecl(); |
149 | } |
150 | |
151 | case NestedNameSpecifier::Global: |
152 | return Context.getTranslationUnitDecl(); |
153 | |
154 | case NestedNameSpecifier::Super: |
155 | return NNS->getAsRecordDecl(); |
156 | } |
157 | |
158 | llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); |
159 | } |
160 | |
161 | bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { |
162 | if (!SS.isSet() || SS.isInvalid()) |
163 | return false; |
164 | |
165 | return SS.getScopeRep()->isDependent(); |
166 | } |
167 | |
168 | CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) { |
169 | assert(getLangOpts().CPlusPlus && "Only callable in C++"); |
170 | assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed"); |
171 | |
172 | if (!NNS->getAsType()) |
173 | return nullptr; |
174 | |
175 | QualType T = QualType(NNS->getAsType(), 0); |
176 | return ::getCurrentInstantiationOf(T, CurContext); |
177 | } |
178 | |
179 | /// Require that the context specified by SS be complete. |
180 | /// |
181 | /// If SS refers to a type, this routine checks whether the type is |
182 | /// complete enough (or can be made complete enough) for name lookup |
183 | /// into the DeclContext. A type that is not yet completed can be |
184 | /// considered "complete enough" if it is a class/struct/union/enum |
185 | /// that is currently being defined. Or, if we have a type that names |
186 | /// a class template specialization that is not a complete type, we |
187 | /// will attempt to instantiate that class template. |
188 | bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, |
189 | DeclContext *DC) { |
190 | assert(DC && "given null context"); |
191 | |
192 | TagDecl *tag = dyn_cast<TagDecl>(Val: DC); |
193 | |
194 | // If this is a dependent type, then we consider it complete. |
195 | // FIXME: This is wrong; we should require a (visible) definition to |
196 | // exist in this case too. |
197 | if (!tag || tag->isDependentContext()) |
198 | return false; |
199 | |
200 | // Grab the tag definition, if there is one. |
201 | QualType type = Context.getTypeDeclType(tag); |
202 | tag = type->getAsTagDecl(); |
203 | |
204 | // If we're currently defining this type, then lookup into the |
205 | // type is okay: don't complain that it isn't complete yet. |
206 | if (tag->isBeingDefined()) |
207 | return false; |
208 | |
209 | SourceLocation loc = SS.getLastQualifierNameLoc(); |
210 | if (loc.isInvalid()) loc = SS.getRange().getBegin(); |
211 | |
212 | // The type must be complete. |
213 | if (RequireCompleteType(loc, type, diag::err_incomplete_nested_name_spec, |
214 | SS.getRange())) { |
215 | SS.SetInvalid(SS.getRange()); |
216 | return true; |
217 | } |
218 | |
219 | if (auto *EnumD = dyn_cast<EnumDecl>(Val: tag)) |
220 | // Fixed enum types and scoped enum instantiations are complete, but they |
221 | // aren't valid as scopes until we see or instantiate their definition. |
222 | return RequireCompleteEnumDecl(D: EnumD, L: loc, SS: &SS); |
223 | |
224 | return false; |
225 | } |
226 | |
227 | /// Require that the EnumDecl is completed with its enumerators defined or |
228 | /// instantiated. SS, if provided, is the ScopeRef parsed. |
229 | /// |
230 | bool Sema::RequireCompleteEnumDecl(EnumDecl *EnumD, SourceLocation L, |
231 | CXXScopeSpec *SS) { |
232 | if (EnumD->isCompleteDefinition()) { |
233 | // If we know about the definition but it is not visible, complain. |
234 | NamedDecl *SuggestedDef = nullptr; |
235 | if (!hasReachableDefinition(EnumD, &SuggestedDef, |
236 | /*OnlyNeedComplete*/ false)) { |
237 | // If the user is going to see an error here, recover by making the |
238 | // definition visible. |
239 | bool TreatAsComplete = !isSFINAEContext(); |
240 | diagnoseMissingImport(Loc: L, Decl: SuggestedDef, MIK: MissingImportKind::Definition, |
241 | /*Recover*/ TreatAsComplete); |
242 | return !TreatAsComplete; |
243 | } |
244 | return false; |
245 | } |
246 | |
247 | // Try to instantiate the definition, if this is a specialization of an |
248 | // enumeration temploid. |
249 | if (EnumDecl *Pattern = EnumD->getInstantiatedFromMemberEnum()) { |
250 | MemberSpecializationInfo *MSI = EnumD->getMemberSpecializationInfo(); |
251 | if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { |
252 | if (InstantiateEnum(PointOfInstantiation: L, Instantiation: EnumD, Pattern, |
253 | TemplateArgs: getTemplateInstantiationArgs(EnumD), |
254 | TSK: TSK_ImplicitInstantiation)) { |
255 | if (SS) |
256 | SS->SetInvalid(SS->getRange()); |
257 | return true; |
258 | } |
259 | return false; |
260 | } |
261 | } |
262 | |
263 | if (SS) { |
264 | Diag(L, diag::err_incomplete_nested_name_spec) |
265 | << QualType(EnumD->getTypeForDecl(), 0) << SS->getRange(); |
266 | SS->SetInvalid(SS->getRange()); |
267 | } else { |
268 | Diag(L, diag::err_incomplete_enum) << QualType(EnumD->getTypeForDecl(), 0); |
269 | Diag(EnumD->getLocation(), diag::note_declared_at); |
270 | } |
271 | |
272 | return true; |
273 | } |
274 | |
275 | bool Sema::ActOnCXXGlobalScopeSpecifier(SourceLocation CCLoc, |
276 | CXXScopeSpec &SS) { |
277 | SS.MakeGlobal(Context, ColonColonLoc: CCLoc); |
278 | return false; |
279 | } |
280 | |
281 | bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc, |
282 | SourceLocation ColonColonLoc, |
283 | CXXScopeSpec &SS) { |
284 | if (getCurLambda()) { |
285 | Diag(SuperLoc, diag::err_super_in_lambda_unsupported); |
286 | return true; |
287 | } |
288 | |
289 | CXXRecordDecl *RD = nullptr; |
290 | for (Scope *S = getCurScope(); S; S = S->getParent()) { |
291 | if (S->isFunctionScope()) { |
292 | if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Val: S->getEntity())) |
293 | RD = MD->getParent(); |
294 | break; |
295 | } |
296 | if (S->isClassScope()) { |
297 | RD = cast<CXXRecordDecl>(Val: S->getEntity()); |
298 | break; |
299 | } |
300 | } |
301 | |
302 | if (!RD) { |
303 | Diag(SuperLoc, diag::err_invalid_super_scope); |
304 | return true; |
305 | } else if (RD->getNumBases() == 0) { |
306 | Diag(SuperLoc, diag::err_no_base_classes) << RD->getName(); |
307 | return true; |
308 | } |
309 | |
310 | SS.MakeSuper(Context, RD, SuperLoc, ColonColonLoc); |
311 | return false; |
312 | } |
313 | |
314 | bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD, |
315 | bool *IsExtension) { |
316 | if (!SD) |
317 | return false; |
318 | |
319 | SD = SD->getUnderlyingDecl(); |
320 | |
321 | // Namespace and namespace aliases are fine. |
322 | if (isa<NamespaceDecl>(Val: SD)) |
323 | return true; |
324 | |
325 | if (!isa<TypeDecl>(Val: SD)) |
326 | return false; |
327 | |
328 | // Determine whether we have a class (or, in C++11, an enum) or |
329 | // a typedef thereof. If so, build the nested-name-specifier. |
330 | QualType T = Context.getTypeDeclType(Decl: cast<TypeDecl>(Val: SD)); |
331 | if (T->isDependentType()) |
332 | return true; |
333 | if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(Val: SD)) { |
334 | if (TD->getUnderlyingType()->isRecordType()) |
335 | return true; |
336 | if (TD->getUnderlyingType()->isEnumeralType()) { |
337 | if (Context.getLangOpts().CPlusPlus11) |
338 | return true; |
339 | if (IsExtension) |
340 | *IsExtension = true; |
341 | } |
342 | } else if (isa<RecordDecl>(Val: SD)) { |
343 | return true; |
344 | } else if (isa<EnumDecl>(Val: SD)) { |
345 | if (Context.getLangOpts().CPlusPlus11) |
346 | return true; |
347 | if (IsExtension) |
348 | *IsExtension = true; |
349 | } |
350 | |
351 | return false; |
352 | } |
353 | |
354 | NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) { |
355 | if (!S || !NNS) |
356 | return nullptr; |
357 | |
358 | while (NNS->getPrefix()) |
359 | NNS = NNS->getPrefix(); |
360 | |
361 | if (NNS->getKind() != NestedNameSpecifier::Identifier) |
362 | return nullptr; |
363 | |
364 | LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(), |
365 | LookupNestedNameSpecifierName); |
366 | LookupName(R&: Found, S); |
367 | assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet"); |
368 | |
369 | if (!Found.isSingleResult()) |
370 | return nullptr; |
371 | |
372 | NamedDecl *Result = Found.getFoundDecl(); |
373 | if (isAcceptableNestedNameSpecifier(SD: Result)) |
374 | return Result; |
375 | |
376 | return nullptr; |
377 | } |
378 | |
379 | namespace { |
380 | |
381 | // Callback to only accept typo corrections that can be a valid C++ member |
382 | // initializer: either a non-static field member or a base class. |
383 | class NestedNameSpecifierValidatorCCC final |
384 | : public CorrectionCandidateCallback { |
385 | public: |
386 | explicit NestedNameSpecifierValidatorCCC(Sema &SRef) |
387 | : SRef(SRef) {} |
388 | |
389 | bool ValidateCandidate(const TypoCorrection &candidate) override { |
390 | return SRef.isAcceptableNestedNameSpecifier(SD: candidate.getCorrectionDecl()); |
391 | } |
392 | |
393 | std::unique_ptr<CorrectionCandidateCallback> clone() override { |
394 | return std::make_unique<NestedNameSpecifierValidatorCCC>(args&: *this); |
395 | } |
396 | |
397 | private: |
398 | Sema &SRef; |
399 | }; |
400 | |
401 | } |
402 | |
403 | bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, |
404 | bool EnteringContext, CXXScopeSpec &SS, |
405 | NamedDecl *ScopeLookupResult, |
406 | bool ErrorRecoveryLookup, |
407 | bool *IsCorrectedToColon, |
408 | bool OnlyNamespace) { |
409 | if (IdInfo.Identifier->isEditorPlaceholder()) |
410 | return true; |
411 | LookupResult Found(*this, IdInfo.Identifier, IdInfo.IdentifierLoc, |
412 | OnlyNamespace ? LookupNamespaceName |
413 | : LookupNestedNameSpecifierName); |
414 | QualType ObjectType = GetTypeFromParser(Ty: IdInfo.ObjectType); |
415 | |
416 | // Determine where to perform name lookup |
417 | DeclContext *LookupCtx = nullptr; |
418 | bool isDependent = false; |
419 | if (IsCorrectedToColon) |
420 | *IsCorrectedToColon = false; |
421 | if (!ObjectType.isNull()) { |
422 | // This nested-name-specifier occurs in a member access expression, e.g., |
423 | // x->B::f, and we are looking into the type of the object. |
424 | assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); |
425 | LookupCtx = computeDeclContext(T: ObjectType); |
426 | isDependent = ObjectType->isDependentType(); |
427 | } else if (SS.isSet()) { |
428 | // This nested-name-specifier occurs after another nested-name-specifier, |
429 | // so look into the context associated with the prior nested-name-specifier. |
430 | LookupCtx = computeDeclContext(SS, EnteringContext); |
431 | isDependent = isDependentScopeSpecifier(SS); |
432 | Found.setContextRange(SS.getRange()); |
433 | } |
434 | |
435 | bool ObjectTypeSearchedInScope = false; |
436 | if (LookupCtx) { |
437 | // Perform "qualified" name lookup into the declaration context we |
438 | // computed, which is either the type of the base of a member access |
439 | // expression or the declaration context associated with a prior |
440 | // nested-name-specifier. |
441 | |
442 | // The declaration context must be complete. |
443 | if (!LookupCtx->isDependentContext() && |
444 | RequireCompleteDeclContext(SS, DC: LookupCtx)) |
445 | return true; |
446 | |
447 | LookupQualifiedName(R&: Found, LookupCtx); |
448 | |
449 | if (!ObjectType.isNull() && Found.empty()) { |
450 | // C++ [basic.lookup.classref]p4: |
451 | // If the id-expression in a class member access is a qualified-id of |
452 | // the form |
453 | // |
454 | // class-name-or-namespace-name::... |
455 | // |
456 | // the class-name-or-namespace-name following the . or -> operator is |
457 | // looked up both in the context of the entire postfix-expression and in |
458 | // the scope of the class of the object expression. If the name is found |
459 | // only in the scope of the class of the object expression, the name |
460 | // shall refer to a class-name. If the name is found only in the |
461 | // context of the entire postfix-expression, the name shall refer to a |
462 | // class-name or namespace-name. [...] |
463 | // |
464 | // Qualified name lookup into a class will not find a namespace-name, |
465 | // so we do not need to diagnose that case specifically. However, |
466 | // this qualified name lookup may find nothing. In that case, perform |
467 | // unqualified name lookup in the given scope (if available) or |
468 | // reconstruct the result from when name lookup was performed at template |
469 | // definition time. |
470 | if (S) |
471 | LookupName(R&: Found, S); |
472 | else if (ScopeLookupResult) |
473 | Found.addDecl(D: ScopeLookupResult); |
474 | |
475 | ObjectTypeSearchedInScope = true; |
476 | } |
477 | } else if (!isDependent) { |
478 | // Perform unqualified name lookup in the current scope. |
479 | LookupName(R&: Found, S); |
480 | } |
481 | |
482 | if (Found.isAmbiguous()) |
483 | return true; |
484 | |
485 | // If we performed lookup into a dependent context and did not find anything, |
486 | // that's fine: just build a dependent nested-name-specifier. |
487 | if (Found.empty() && isDependent && |
488 | !(LookupCtx && LookupCtx->isRecord() && |
489 | (!cast<CXXRecordDecl>(Val: LookupCtx)->hasDefinition() || |
490 | !cast<CXXRecordDecl>(Val: LookupCtx)->hasAnyDependentBases()))) { |
491 | // Don't speculate if we're just trying to improve error recovery. |
492 | if (ErrorRecoveryLookup) |
493 | return true; |
494 | |
495 | // We were not able to compute the declaration context for a dependent |
496 | // base object type or prior nested-name-specifier, so this |
497 | // nested-name-specifier refers to an unknown specialization. Just build |
498 | // a dependent nested-name-specifier. |
499 | SS.Extend(Context, Identifier: IdInfo.Identifier, IdentifierLoc: IdInfo.IdentifierLoc, ColonColonLoc: IdInfo.CCLoc); |
500 | return false; |
501 | } |
502 | |
503 | if (Found.empty() && !ErrorRecoveryLookup) { |
504 | // If identifier is not found as class-name-or-namespace-name, but is found |
505 | // as other entity, don't look for typos. |
506 | LookupResult R(*this, Found.getLookupNameInfo(), LookupOrdinaryName); |
507 | if (LookupCtx) |
508 | LookupQualifiedName(R, LookupCtx); |
509 | else if (S && !isDependent) |
510 | LookupName(R, S); |
511 | if (!R.empty()) { |
512 | // Don't diagnose problems with this speculative lookup. |
513 | R.suppressDiagnostics(); |
514 | // The identifier is found in ordinary lookup. If correction to colon is |
515 | // allowed, suggest replacement to ':'. |
516 | if (IsCorrectedToColon) { |
517 | *IsCorrectedToColon = true; |
518 | Diag(IdInfo.CCLoc, diag::err_nested_name_spec_is_not_class) |
519 | << IdInfo.Identifier << getLangOpts().CPlusPlus |
520 | << FixItHint::CreateReplacement(IdInfo.CCLoc, ":"); |
521 | if (NamedDecl *ND = R.getAsSingle<NamedDecl>()) |
522 | Diag(ND->getLocation(), diag::note_declared_at); |
523 | return true; |
524 | } |
525 | // Replacement '::' -> ':' is not allowed, just issue respective error. |
526 | Diag(R.getNameLoc(), OnlyNamespace |
527 | ? unsigned(diag::err_expected_namespace_name) |
528 | : unsigned(diag::err_expected_class_or_namespace)) |
529 | << IdInfo.Identifier << getLangOpts().CPlusPlus; |
530 | if (NamedDecl *ND = R.getAsSingle<NamedDecl>()) |
531 | Diag(ND->getLocation(), diag::note_entity_declared_at) |
532 | << IdInfo.Identifier; |
533 | return true; |
534 | } |
535 | } |
536 | |
537 | if (Found.empty() && !ErrorRecoveryLookup && !getLangOpts().MSVCCompat) { |
538 | // We haven't found anything, and we're not recovering from a |
539 | // different kind of error, so look for typos. |
540 | DeclarationName Name = Found.getLookupName(); |
541 | Found.clear(); |
542 | NestedNameSpecifierValidatorCCC CCC(*this); |
543 | if (TypoCorrection Corrected = CorrectTypo( |
544 | Typo: Found.getLookupNameInfo(), LookupKind: Found.getLookupKind(), S, SS: &SS, CCC, |
545 | Mode: CorrectTypoKind::ErrorRecovery, MemberContext: LookupCtx, EnteringContext)) { |
546 | if (LookupCtx) { |
547 | bool DroppedSpecifier = |
548 | Corrected.WillReplaceSpecifier() && |
549 | Name.getAsString() == Corrected.getAsString(LO: getLangOpts()); |
550 | if (DroppedSpecifier) |
551 | SS.clear(); |
552 | diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest) |
553 | << Name << LookupCtx << DroppedSpecifier |
554 | << SS.getRange()); |
555 | } else |
556 | diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest) |
557 | << Name); |
558 | |
559 | if (Corrected.getCorrectionSpecifier()) |
560 | SS.MakeTrivial(Context, Qualifier: Corrected.getCorrectionSpecifier(), |
561 | R: SourceRange(Found.getNameLoc())); |
562 | |
563 | if (NamedDecl *ND = Corrected.getFoundDecl()) |
564 | Found.addDecl(D: ND); |
565 | Found.setLookupName(Corrected.getCorrection()); |
566 | } else { |
567 | Found.setLookupName(IdInfo.Identifier); |
568 | } |
569 | } |
570 | |
571 | NamedDecl *SD = |
572 | Found.isSingleResult() ? Found.getRepresentativeDecl() : nullptr; |
573 | bool IsExtension = false; |
574 | bool AcceptSpec = isAcceptableNestedNameSpecifier(SD, IsExtension: &IsExtension); |
575 | if (!AcceptSpec && IsExtension) { |
576 | AcceptSpec = true; |
577 | Diag(IdInfo.IdentifierLoc, diag::ext_nested_name_spec_is_enum); |
578 | } |
579 | if (AcceptSpec) { |
580 | if (!ObjectType.isNull() && !ObjectTypeSearchedInScope && |
581 | !getLangOpts().CPlusPlus11) { |
582 | // C++03 [basic.lookup.classref]p4: |
583 | // [...] If the name is found in both contexts, the |
584 | // class-name-or-namespace-name shall refer to the same entity. |
585 | // |
586 | // We already found the name in the scope of the object. Now, look |
587 | // into the current scope (the scope of the postfix-expression) to |
588 | // see if we can find the same name there. As above, if there is no |
589 | // scope, reconstruct the result from the template instantiation itself. |
590 | // |
591 | // Note that C++11 does *not* perform this redundant lookup. |
592 | NamedDecl *OuterDecl; |
593 | if (S) { |
594 | LookupResult FoundOuter(*this, IdInfo.Identifier, IdInfo.IdentifierLoc, |
595 | LookupNestedNameSpecifierName); |
596 | LookupName(R&: FoundOuter, S); |
597 | OuterDecl = FoundOuter.getAsSingle<NamedDecl>(); |
598 | } else |
599 | OuterDecl = ScopeLookupResult; |
600 | |
601 | if (isAcceptableNestedNameSpecifier(SD: OuterDecl) && |
602 | OuterDecl->getCanonicalDecl() != SD->getCanonicalDecl() && |
603 | (!isa<TypeDecl>(Val: OuterDecl) || !isa<TypeDecl>(Val: SD) || |
604 | !Context.hasSameType( |
605 | T1: Context.getTypeDeclType(Decl: cast<TypeDecl>(Val: OuterDecl)), |
606 | T2: Context.getTypeDeclType(Decl: cast<TypeDecl>(Val: SD))))) { |
607 | if (ErrorRecoveryLookup) |
608 | return true; |
609 | |
610 | Diag(IdInfo.IdentifierLoc, |
611 | diag::err_nested_name_member_ref_lookup_ambiguous) |
612 | << IdInfo.Identifier; |
613 | Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type) |
614 | << ObjectType; |
615 | Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope); |
616 | |
617 | // Fall through so that we'll pick the name we found in the object |
618 | // type, since that's probably what the user wanted anyway. |
619 | } |
620 | } |
621 | |
622 | if (auto *TD = dyn_cast_or_null<TypedefNameDecl>(Val: SD)) |
623 | MarkAnyDeclReferenced(Loc: TD->getLocation(), D: TD, /*OdrUse=*/MightBeOdrUse: false); |
624 | |
625 | // If we're just performing this lookup for error-recovery purposes, |
626 | // don't extend the nested-name-specifier. Just return now. |
627 | if (ErrorRecoveryLookup) |
628 | return false; |
629 | |
630 | // The use of a nested name specifier may trigger deprecation warnings. |
631 | DiagnoseUseOfDecl(D: SD, Locs: IdInfo.CCLoc); |
632 | |
633 | if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Val: SD)) { |
634 | SS.Extend(Context, Namespace, NamespaceLoc: IdInfo.IdentifierLoc, ColonColonLoc: IdInfo.CCLoc); |
635 | return false; |
636 | } |
637 | |
638 | if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(Val: SD)) { |
639 | SS.Extend(Context, Alias, AliasLoc: IdInfo.IdentifierLoc, ColonColonLoc: IdInfo.CCLoc); |
640 | return false; |
641 | } |
642 | |
643 | QualType T = |
644 | Context.getTypeDeclType(Decl: cast<TypeDecl>(Val: SD->getUnderlyingDecl())); |
645 | |
646 | if (T->isEnumeralType()) |
647 | Diag(IdInfo.IdentifierLoc, diag::warn_cxx98_compat_enum_nested_name_spec); |
648 | |
649 | TypeLocBuilder TLB; |
650 | if (const auto *USD = dyn_cast<UsingShadowDecl>(Val: SD)) { |
651 | T = Context.getUsingType(Found: USD, Underlying: T); |
652 | TLB.pushTypeSpec(T).setNameLoc(IdInfo.IdentifierLoc); |
653 | } else if (isa<InjectedClassNameType>(Val: T)) { |
654 | InjectedClassNameTypeLoc InjectedTL |
655 | = TLB.push<InjectedClassNameTypeLoc>(T); |
656 | InjectedTL.setNameLoc(IdInfo.IdentifierLoc); |
657 | } else if (isa<RecordType>(Val: T)) { |
658 | RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T); |
659 | RecordTL.setNameLoc(IdInfo.IdentifierLoc); |
660 | } else if (isa<TypedefType>(Val: T)) { |
661 | TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T); |
662 | TypedefTL.setNameLoc(IdInfo.IdentifierLoc); |
663 | } else if (isa<EnumType>(Val: T)) { |
664 | EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T); |
665 | EnumTL.setNameLoc(IdInfo.IdentifierLoc); |
666 | } else if (isa<TemplateTypeParmType>(Val: T)) { |
667 | TemplateTypeParmTypeLoc TemplateTypeTL |
668 | = TLB.push<TemplateTypeParmTypeLoc>(T); |
669 | TemplateTypeTL.setNameLoc(IdInfo.IdentifierLoc); |
670 | } else if (isa<UnresolvedUsingType>(Val: T)) { |
671 | UnresolvedUsingTypeLoc UnresolvedTL |
672 | = TLB.push<UnresolvedUsingTypeLoc>(T); |
673 | UnresolvedTL.setNameLoc(IdInfo.IdentifierLoc); |
674 | } else if (isa<SubstTemplateTypeParmType>(Val: T)) { |
675 | SubstTemplateTypeParmTypeLoc TL |
676 | = TLB.push<SubstTemplateTypeParmTypeLoc>(T); |
677 | TL.setNameLoc(IdInfo.IdentifierLoc); |
678 | } else if (isa<SubstTemplateTypeParmPackType>(Val: T)) { |
679 | SubstTemplateTypeParmPackTypeLoc TL |
680 | = TLB.push<SubstTemplateTypeParmPackTypeLoc>(T); |
681 | TL.setNameLoc(IdInfo.IdentifierLoc); |
682 | } else { |
683 | llvm_unreachable("Unhandled TypeDecl node in nested-name-specifier"); |
684 | } |
685 | |
686 | SS.Extend(Context, TL: TLB.getTypeLocInContext(Context, T), ColonColonLoc: IdInfo.CCLoc); |
687 | return false; |
688 | } |
689 | |
690 | // Otherwise, we have an error case. If we don't want diagnostics, just |
691 | // return an error now. |
692 | if (ErrorRecoveryLookup) |
693 | return true; |
694 | |
695 | // If we didn't find anything during our lookup, try again with |
696 | // ordinary name lookup, which can help us produce better error |
697 | // messages. |
698 | if (Found.empty()) { |
699 | Found.clear(Kind: LookupOrdinaryName); |
700 | LookupName(R&: Found, S); |
701 | } |
702 | |
703 | // In Microsoft mode, if we are within a templated function and we can't |
704 | // resolve Identifier, then extend the SS with Identifier. This will have |
705 | // the effect of resolving Identifier during template instantiation. |
706 | // The goal is to be able to resolve a function call whose |
707 | // nested-name-specifier is located inside a dependent base class. |
708 | // Example: |
709 | // |
710 | // class C { |
711 | // public: |
712 | // static void foo2() { } |
713 | // }; |
714 | // template <class T> class A { public: typedef C D; }; |
715 | // |
716 | // template <class T> class B : public A<T> { |
717 | // public: |
718 | // void foo() { D::foo2(); } |
719 | // }; |
720 | if (getLangOpts().MSVCCompat) { |
721 | DeclContext *DC = LookupCtx ? LookupCtx : CurContext; |
722 | if (DC->isDependentContext() && DC->isFunctionOrMethod()) { |
723 | CXXRecordDecl *ContainingClass = dyn_cast<CXXRecordDecl>(Val: DC->getParent()); |
724 | if (ContainingClass && ContainingClass->hasAnyDependentBases()) { |
725 | Diag(IdInfo.IdentifierLoc, |
726 | diag::ext_undeclared_unqual_id_with_dependent_base) |
727 | << IdInfo.Identifier << ContainingClass; |
728 | // Fake up a nested-name-specifier that starts with the |
729 | // injected-class-name of the enclosing class. |
730 | QualType T = Context.getTypeDeclType(ContainingClass); |
731 | TypeLocBuilder TLB; |
732 | TLB.pushTrivial(Context, T, Loc: IdInfo.IdentifierLoc); |
733 | SS.Extend(Context, TL: TLB.getTypeLocInContext(Context, T), |
734 | ColonColonLoc: IdInfo.IdentifierLoc); |
735 | // Add the identifier to form a dependent name. |
736 | SS.Extend(Context, Identifier: IdInfo.Identifier, IdentifierLoc: IdInfo.IdentifierLoc, |
737 | ColonColonLoc: IdInfo.CCLoc); |
738 | return false; |
739 | } |
740 | } |
741 | } |
742 | |
743 | if (!Found.empty()) { |
744 | if (TypeDecl *TD = Found.getAsSingle<TypeDecl>()) { |
745 | Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace) |
746 | << Context.getTypeDeclType(TD) << getLangOpts().CPlusPlus; |
747 | } else if (Found.getAsSingle<TemplateDecl>()) { |
748 | ParsedType SuggestedType; |
749 | DiagnoseUnknownTypeName(II&: IdInfo.Identifier, IILoc: IdInfo.IdentifierLoc, S, SS: &SS, |
750 | SuggestedType); |
751 | } else { |
752 | Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace) |
753 | << IdInfo.Identifier << getLangOpts().CPlusPlus; |
754 | if (NamedDecl *ND = Found.getAsSingle<NamedDecl>()) |
755 | Diag(ND->getLocation(), diag::note_entity_declared_at) |
756 | << IdInfo.Identifier; |
757 | } |
758 | } else if (SS.isSet()) |
759 | Diag(IdInfo.IdentifierLoc, diag::err_no_member) << IdInfo.Identifier |
760 | << LookupCtx << SS.getRange(); |
761 | else |
762 | Diag(IdInfo.IdentifierLoc, diag::err_undeclared_var_use) |
763 | << IdInfo.Identifier; |
764 | |
765 | return true; |
766 | } |
767 | |
768 | bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, |
769 | bool EnteringContext, CXXScopeSpec &SS, |
770 | bool *IsCorrectedToColon, |
771 | bool OnlyNamespace) { |
772 | if (SS.isInvalid()) |
773 | return true; |
774 | |
775 | return BuildCXXNestedNameSpecifier(S, IdInfo, EnteringContext, SS, |
776 | /*ScopeLookupResult=*/nullptr, ErrorRecoveryLookup: false, |
777 | IsCorrectedToColon, OnlyNamespace); |
778 | } |
779 | |
780 | bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, |
781 | const DeclSpec &DS, |
782 | SourceLocation ColonColonLoc) { |
783 | if (SS.isInvalid() || DS.getTypeSpecType() == DeclSpec::TST_error) |
784 | return true; |
785 | |
786 | assert(DS.getTypeSpecType() == DeclSpec::TST_decltype); |
787 | |
788 | QualType T = BuildDecltypeType(E: DS.getRepAsExpr()); |
789 | if (T.isNull()) |
790 | return true; |
791 | |
792 | if (!T->isDependentType() && !T->getAs<TagType>()) { |
793 | Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class_or_namespace) |
794 | << T << getLangOpts().CPlusPlus; |
795 | return true; |
796 | } |
797 | |
798 | TypeLocBuilder TLB; |
799 | DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T); |
800 | DecltypeTL.setDecltypeLoc(DS.getTypeSpecTypeLoc()); |
801 | DecltypeTL.setRParenLoc(DS.getTypeofParensRange().getEnd()); |
802 | SS.Extend(Context, TL: TLB.getTypeLocInContext(Context, T), ColonColonLoc); |
803 | return false; |
804 | } |
805 | |
806 | bool Sema::ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS, |
807 | const DeclSpec &DS, |
808 | SourceLocation ColonColonLoc, |
809 | QualType Type) { |
810 | if (SS.isInvalid() || DS.getTypeSpecType() == DeclSpec::TST_error) |
811 | return true; |
812 | |
813 | assert(DS.getTypeSpecType() == DeclSpec::TST_typename_pack_indexing); |
814 | |
815 | if (Type.isNull()) |
816 | return true; |
817 | |
818 | TypeLocBuilder TLB; |
819 | TLB.pushTrivial(Context&: getASTContext(), |
820 | T: cast<PackIndexingType>(Val: Type.getTypePtr())->getPattern(), |
821 | Loc: DS.getBeginLoc()); |
822 | PackIndexingTypeLoc PIT = TLB.push<PackIndexingTypeLoc>(T: Type); |
823 | PIT.setEllipsisLoc(DS.getEllipsisLoc()); |
824 | SS.Extend(Context, TL: TLB.getTypeLocInContext(Context, T: Type), ColonColonLoc); |
825 | return false; |
826 | } |
827 | |
828 | bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, |
829 | NestedNameSpecInfo &IdInfo, |
830 | bool EnteringContext) { |
831 | if (SS.isInvalid()) |
832 | return false; |
833 | |
834 | return !BuildCXXNestedNameSpecifier(S, IdInfo, EnteringContext, SS, |
835 | /*ScopeLookupResult=*/nullptr, ErrorRecoveryLookup: true); |
836 | } |
837 | |
838 | bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, |
839 | CXXScopeSpec &SS, |
840 | SourceLocation TemplateKWLoc, |
841 | TemplateTy OpaqueTemplate, |
842 | SourceLocation TemplateNameLoc, |
843 | SourceLocation LAngleLoc, |
844 | ASTTemplateArgsPtr TemplateArgsIn, |
845 | SourceLocation RAngleLoc, |
846 | SourceLocation CCLoc, |
847 | bool EnteringContext) { |
848 | if (SS.isInvalid()) |
849 | return true; |
850 | |
851 | TemplateName Template = OpaqueTemplate.get(); |
852 | |
853 | // Translate the parser's template argument list in our AST format. |
854 | TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); |
855 | translateTemplateArguments(In: TemplateArgsIn, Out&: TemplateArgs); |
856 | |
857 | DependentTemplateName *DTN = Template.getAsDependentTemplateName(); |
858 | if (DTN && DTN->getName().getIdentifier()) { |
859 | // Handle a dependent template specialization for which we cannot resolve |
860 | // the template name. |
861 | assert(DTN->getQualifier() == SS.getScopeRep()); |
862 | QualType T = Context.getDependentTemplateSpecializationType( |
863 | Keyword: ElaboratedTypeKeyword::None, |
864 | Name: {/*Qualifier=*/nullptr, DTN->getName().getIdentifier(), |
865 | TemplateKWLoc.isValid()}, |
866 | Args: TemplateArgs.arguments()); |
867 | |
868 | // Create source-location information for this type. |
869 | TypeLocBuilder Builder; |
870 | DependentTemplateSpecializationTypeLoc SpecTL |
871 | = Builder.push<DependentTemplateSpecializationTypeLoc>(T); |
872 | SpecTL.setElaboratedKeywordLoc(SourceLocation()); |
873 | SpecTL.setQualifierLoc(NestedNameSpecifierLoc()); |
874 | SpecTL.setTemplateKeywordLoc(TemplateKWLoc); |
875 | SpecTL.setTemplateNameLoc(TemplateNameLoc); |
876 | SpecTL.setLAngleLoc(LAngleLoc); |
877 | SpecTL.setRAngleLoc(RAngleLoc); |
878 | for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) |
879 | SpecTL.setArgLocInfo(i: I, AI: TemplateArgs[I].getLocInfo()); |
880 | |
881 | SS.Extend(Context, TL: Builder.getTypeLocInContext(Context, T), ColonColonLoc: CCLoc); |
882 | return false; |
883 | } |
884 | |
885 | // If we assumed an undeclared identifier was a template name, try to |
886 | // typo-correct it now. |
887 | if (Template.getAsAssumedTemplateName() && |
888 | resolveAssumedTemplateNameAsType(S, Name&: Template, NameLoc: TemplateNameLoc)) |
889 | return true; |
890 | |
891 | TemplateDecl *TD = Template.getAsTemplateDecl(); |
892 | if (Template.getAsOverloadedTemplate() || DTN || |
893 | isa<FunctionTemplateDecl>(Val: TD) || isa<VarTemplateDecl>(Val: TD)) { |
894 | SourceRange R(TemplateNameLoc, RAngleLoc); |
895 | if (SS.getRange().isValid()) |
896 | R.setBegin(SS.getRange().getBegin()); |
897 | |
898 | Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier) |
899 | << isa_and_nonnull<VarTemplateDecl>(TD) << Template << R; |
900 | NoteAllFoundTemplates(Name: Template); |
901 | return true; |
902 | } |
903 | |
904 | // We were able to resolve the template name to an actual template. |
905 | // Build an appropriate nested-name-specifier. |
906 | QualType T = CheckTemplateIdType(Template, TemplateLoc: TemplateNameLoc, TemplateArgs); |
907 | if (T.isNull()) |
908 | return true; |
909 | |
910 | // Alias template specializations can produce types which are not valid |
911 | // nested name specifiers. |
912 | if (!T->isDependentType() && !T->getAs<TagType>()) { |
913 | Diag(TemplateNameLoc, diag::err_nested_name_spec_non_tag) << T; |
914 | NoteAllFoundTemplates(Name: Template); |
915 | return true; |
916 | } |
917 | |
918 | // Provide source-location information for the template specialization type. |
919 | TypeLocBuilder Builder; |
920 | TemplateSpecializationTypeLoc SpecTL |
921 | = Builder.push<TemplateSpecializationTypeLoc>(T); |
922 | SpecTL.setTemplateKeywordLoc(TemplateKWLoc); |
923 | SpecTL.setTemplateNameLoc(TemplateNameLoc); |
924 | SpecTL.setLAngleLoc(LAngleLoc); |
925 | SpecTL.setRAngleLoc(RAngleLoc); |
926 | for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) |
927 | SpecTL.setArgLocInfo(i: I, AI: TemplateArgs[I].getLocInfo()); |
928 | |
929 | SS.Extend(Context, TL: Builder.getTypeLocInContext(Context, T), ColonColonLoc: CCLoc); |
930 | return false; |
931 | } |
932 | |
933 | namespace { |
934 | /// A structure that stores a nested-name-specifier annotation, |
935 | /// including both the nested-name-specifier |
936 | struct NestedNameSpecifierAnnotation { |
937 | NestedNameSpecifier *NNS; |
938 | }; |
939 | } |
940 | |
941 | void *Sema::SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS) { |
942 | if (SS.isEmpty() || SS.isInvalid()) |
943 | return nullptr; |
944 | |
945 | void *Mem = Context.Allocate( |
946 | Size: (sizeof(NestedNameSpecifierAnnotation) + SS.location_size()), |
947 | Align: alignof(NestedNameSpecifierAnnotation)); |
948 | NestedNameSpecifierAnnotation *Annotation |
949 | = new (Mem) NestedNameSpecifierAnnotation; |
950 | Annotation->NNS = SS.getScopeRep(); |
951 | memcpy(dest: Annotation + 1, src: SS.location_data(), n: SS.location_size()); |
952 | return Annotation; |
953 | } |
954 | |
955 | void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr, |
956 | SourceRange AnnotationRange, |
957 | CXXScopeSpec &SS) { |
958 | if (!AnnotationPtr) { |
959 | SS.SetInvalid(AnnotationRange); |
960 | return; |
961 | } |
962 | |
963 | NestedNameSpecifierAnnotation *Annotation |
964 | = static_cast<NestedNameSpecifierAnnotation *>(AnnotationPtr); |
965 | SS.Adopt(Other: NestedNameSpecifierLoc(Annotation->NNS, Annotation + 1)); |
966 | } |
967 | |
968 | bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { |
969 | assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); |
970 | |
971 | // Don't enter a declarator context when the current context is an Objective-C |
972 | // declaration. |
973 | if (isa<ObjCContainerDecl>(Val: CurContext) || isa<ObjCMethodDecl>(Val: CurContext)) |
974 | return false; |
975 | |
976 | NestedNameSpecifier *Qualifier = SS.getScopeRep(); |
977 | |
978 | // There are only two places a well-formed program may qualify a |
979 | // declarator: first, when defining a namespace or class member |
980 | // out-of-line, and second, when naming an explicitly-qualified |
981 | // friend function. The latter case is governed by |
982 | // C++03 [basic.lookup.unqual]p10: |
983 | // In a friend declaration naming a member function, a name used |
984 | // in the function declarator and not part of a template-argument |
985 | // in a template-id is first looked up in the scope of the member |
986 | // function's class. If it is not found, or if the name is part of |
987 | // a template-argument in a template-id, the look up is as |
988 | // described for unqualified names in the definition of the class |
989 | // granting friendship. |
990 | // i.e. we don't push a scope unless it's a class member. |
991 | |
992 | switch (Qualifier->getKind()) { |
993 | case NestedNameSpecifier::Global: |
994 | case NestedNameSpecifier::Namespace: |
995 | case NestedNameSpecifier::NamespaceAlias: |
996 | // These are always namespace scopes. We never want to enter a |
997 | // namespace scope from anything but a file context. |
998 | return CurContext->getRedeclContext()->isFileContext(); |
999 | |
1000 | case NestedNameSpecifier::Identifier: |
1001 | case NestedNameSpecifier::TypeSpec: |
1002 | case NestedNameSpecifier::Super: |
1003 | // These are never namespace scopes. |
1004 | return true; |
1005 | } |
1006 | |
1007 | llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); |
1008 | } |
1009 | |
1010 | bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) { |
1011 | assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); |
1012 | |
1013 | if (SS.isInvalid()) return true; |
1014 | |
1015 | DeclContext *DC = computeDeclContext(SS, EnteringContext: true); |
1016 | if (!DC) return true; |
1017 | |
1018 | // Before we enter a declarator's context, we need to make sure that |
1019 | // it is a complete declaration context. |
1020 | if (!DC->isDependentContext() && RequireCompleteDeclContext(SS, DC)) |
1021 | return true; |
1022 | |
1023 | EnterDeclaratorContext(S, DC); |
1024 | |
1025 | // Rebuild the nested name specifier for the new scope. |
1026 | if (DC->isDependentContext()) |
1027 | RebuildNestedNameSpecifierInCurrentInstantiation(SS); |
1028 | |
1029 | return false; |
1030 | } |
1031 | |
1032 | void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { |
1033 | assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); |
1034 | if (SS.isInvalid()) |
1035 | return; |
1036 | assert(!SS.isInvalid() && computeDeclContext(SS, true) && |
1037 | "exiting declarator scope we never really entered"); |
1038 | ExitDeclaratorContext(S); |
1039 | } |
1040 |
Definitions
- getCurrentInstantiationOf
- computeDeclContext
- computeDeclContext
- isDependentScopeSpecifier
- getCurrentInstantiationOf
- RequireCompleteDeclContext
- RequireCompleteEnumDecl
- ActOnCXXGlobalScopeSpecifier
- ActOnSuperScopeSpecifier
- isAcceptableNestedNameSpecifier
- FindFirstQualifierInScope
- NestedNameSpecifierValidatorCCC
- NestedNameSpecifierValidatorCCC
- ValidateCandidate
- clone
- BuildCXXNestedNameSpecifier
- ActOnCXXNestedNameSpecifier
- ActOnCXXNestedNameSpecifierDecltype
- ActOnCXXNestedNameSpecifierIndexedPack
- IsInvalidUnlessNestedName
- ActOnCXXNestedNameSpecifier
- NestedNameSpecifierAnnotation
- SaveNestedNameSpecifierAnnotation
- RestoreNestedNameSpecifierAnnotation
- ShouldEnterDeclaratorScope
- ActOnCXXEnterDeclaratorScope
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more