| //===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements semantic analysis for declarations. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "TypeLocBuilder.h" |
| #include "clang/AST/ASTConsumer.h" |
| #include "clang/AST/ASTContext.h" |
| #include "clang/AST/ASTLambda.h" |
| #include "clang/AST/CXXInheritance.h" |
| #include "clang/AST/CharUnits.h" |
| #include "clang/AST/CommentDiagnostic.h" |
| #include "clang/AST/DeclCXX.h" |
| #include "clang/AST/DeclObjC.h" |
| #include "clang/AST/DeclTemplate.h" |
| #include "clang/AST/EvaluatedExprVisitor.h" |
| #include "clang/AST/Expr.h" |
| #include "clang/AST/ExprCXX.h" |
| #include "clang/AST/NonTrivialTypeVisitor.h" |
| #include "clang/AST/StmtCXX.h" |
| #include "clang/Basic/Builtins.h" |
| #include "clang/Basic/PartialDiagnostic.h" |
| #include "clang/Basic/SourceManager.h" |
| #include "clang/Basic/TargetInfo.h" |
| #include "clang/Lex/HeaderSearch.h" // TODO: Sema shouldn't depend on Lex |
| #include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering. |
| #include "clang/Lex/ModuleLoader.h" // TODO: Sema shouldn't depend on Lex |
| #include "clang/Lex/Preprocessor.h" // Included for isCodeCompletionEnabled() |
| #include "clang/Sema/CXXFieldCollector.h" |
| #include "clang/Sema/DeclSpec.h" |
| #include "clang/Sema/DelayedDiagnostic.h" |
| #include "clang/Sema/Initialization.h" |
| #include "clang/Sema/Lookup.h" |
| #include "clang/Sema/ParsedTemplate.h" |
| #include "clang/Sema/Scope.h" |
| #include "clang/Sema/ScopeInfo.h" |
| #include "clang/Sema/SemaInternal.h" |
| #include "clang/Sema/Template.h" |
| #include "llvm/ADT/SmallString.h" |
| #include "llvm/ADT/Triple.h" |
| #include <algorithm> |
| #include <cstring> |
| #include <functional> |
| #include <unordered_map> |
| |
| using namespace clang; |
| using namespace sema; |
| |
| Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType) { |
| if (OwnedType) { |
| Decl *Group[2] = { OwnedType, Ptr }; |
| return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, 2)); |
| } |
| |
| return DeclGroupPtrTy::make(DeclGroupRef(Ptr)); |
| } |
| |
| namespace { |
| |
| class TypeNameValidatorCCC final : public CorrectionCandidateCallback { |
| public: |
| TypeNameValidatorCCC(bool AllowInvalid, bool WantClass = false, |
| bool AllowTemplates = false, |
| bool AllowNonTemplates = true) |
| : AllowInvalidDecl(AllowInvalid), WantClassName(WantClass), |
| AllowTemplates(AllowTemplates), AllowNonTemplates(AllowNonTemplates) { |
| WantExpressionKeywords = false; |
| WantCXXNamedCasts = false; |
| WantRemainingKeywords = false; |
| } |
| |
| bool ValidateCandidate(const TypoCorrection &candidate) override { |
| if (NamedDecl *ND = candidate.getCorrectionDecl()) { |
| if (!AllowInvalidDecl && ND->isInvalidDecl()) |
| return false; |
| |
| if (getAsTypeTemplateDecl(ND)) |
| return AllowTemplates; |
| |
| bool IsType = isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND); |
| if (!IsType) |
| return false; |
| |
| if (AllowNonTemplates) |
| return true; |
| |
| // An injected-class-name of a class template (specialization) is valid |
| // as a template or as a non-template. |
| if (AllowTemplates) { |
| auto *RD = dyn_cast<CXXRecordDecl>(ND); |
| if (!RD || !RD->isInjectedClassName()) |
| return false; |
| RD = cast<CXXRecordDecl>(RD->getDeclContext()); |
| return RD->getDescribedClassTemplate() || |
| isa<ClassTemplateSpecializationDecl>(RD); |
| } |
| |
| return false; |
| } |
| |
| return !WantClassName && candidate.isKeyword(); |
| } |
| |
| std::unique_ptr<CorrectionCandidateCallback> clone() override { |
| return std::make_unique<TypeNameValidatorCCC>(*this); |
| } |
| |
| private: |
| bool AllowInvalidDecl; |
| bool WantClassName; |
| bool AllowTemplates; |
| bool AllowNonTemplates; |
| }; |
| |
| } // end anonymous namespace |
| |
| /// Determine whether the token kind starts a simple-type-specifier. |
| bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const { |
| switch (Kind) { |
| // FIXME: Take into account the current language when deciding whether a |
| // token kind is a valid type specifier |
| case tok::kw_short: |
| case tok::kw_long: |
| case tok::kw___int64: |
| case tok::kw___int128: |
| case tok::kw_signed: |
| case tok::kw_unsigned: |
| case tok::kw_void: |
| case tok::kw_char: |
| case tok::kw_int: |
| case tok::kw_half: |
| case tok::kw_float: |
| case tok::kw_double: |
| case tok::kw___bf16: |
| case tok::kw__Float16: |
| case tok::kw___float128: |
| case tok::kw___ibm128: |
| case tok::kw_wchar_t: |
| case tok::kw_bool: |
| case tok::kw___underlying_type: |
| case tok::kw___auto_type: |
| return true; |
| |
| case tok::annot_typename: |
| case tok::kw_char16_t: |
| case tok::kw_char32_t: |
| case tok::kw_typeof: |
| case tok::annot_decltype: |
| case tok::kw_decltype: |
| return getLangOpts().CPlusPlus; |
| |
| case tok::kw_char8_t: |
| return getLangOpts().Char8; |
| |
| default: |
| break; |
| } |
| |
| return false; |
| } |
| |
| namespace { |
| enum class UnqualifiedTypeNameLookupResult { |
| NotFound, |
| FoundNonType, |
| FoundType |
| }; |
| } // end anonymous namespace |
| |
| /// Tries to perform unqualified lookup of the type decls in bases for |
| /// dependent class. |
| /// \return \a NotFound if no any decls is found, \a FoundNotType if found not a |
| /// type decl, \a FoundType if only type decls are found. |
| static UnqualifiedTypeNameLookupResult |
| lookupUnqualifiedTypeNameInBase(Sema &S, const IdentifierInfo &II, |
| SourceLocation NameLoc, |
| const CXXRecordDecl *RD) { |
| if (!RD->hasDefinition()) |
| return UnqualifiedTypeNameLookupResult::NotFound; |
| // Look for type decls in base classes. |
| UnqualifiedTypeNameLookupResult FoundTypeDecl = |
| UnqualifiedTypeNameLookupResult::NotFound; |
| for (const auto &Base : RD->bases()) { |
| const CXXRecordDecl *BaseRD = nullptr; |
| if (auto *BaseTT = Base.getType()->getAs<TagType>()) |
| BaseRD = BaseTT->getAsCXXRecordDecl(); |
| else if (auto *TST = Base.getType()->getAs<TemplateSpecializationType>()) { |
| // Look for type decls in dependent base classes that have known primary |
| // templates. |
| if (!TST || !TST->isDependentType()) |
| continue; |
| auto *TD = TST->getTemplateName().getAsTemplateDecl(); |
| if (!TD) |
| continue; |
| if (auto *BasePrimaryTemplate = |
| dyn_cast_or_null<CXXRecordDecl>(TD->getTemplatedDecl())) { |
| if (BasePrimaryTemplate->getCanonicalDecl() != RD->getCanonicalDecl()) |
| BaseRD = BasePrimaryTemplate; |
| else if (auto *CTD = dyn_cast<ClassTemplateDecl>(TD)) { |
| if (const ClassTemplatePartialSpecializationDecl *PS = |
| CTD->findPartialSpecialization(Base.getType())) |
| if (PS->getCanonicalDecl() != RD->getCanonicalDecl()) |
| BaseRD = PS; |
| } |
| } |
| } |
| if (BaseRD) { |
| for (NamedDecl *ND : BaseRD->lookup(&II)) { |
| if (!isa<TypeDecl>(ND)) |
| return UnqualifiedTypeNameLookupResult::FoundNonType; |
| FoundTypeDecl = UnqualifiedTypeNameLookupResult::FoundType; |
| } |
| if (FoundTypeDecl == UnqualifiedTypeNameLookupResult::NotFound) { |
| switch (lookupUnqualifiedTypeNameInBase(S, II, NameLoc, BaseRD)) { |
| case UnqualifiedTypeNameLookupResult::FoundNonType: |
| return UnqualifiedTypeNameLookupResult::FoundNonType; |
| case UnqualifiedTypeNameLookupResult::FoundType: |
| FoundTypeDecl = UnqualifiedTypeNameLookupResult::FoundType; |
| break; |
| case UnqualifiedTypeNameLookupResult::NotFound: |
| break; |
| } |
| } |
| } |
| } |
| |
| return FoundTypeDecl; |
| } |
| |
| static ParsedType recoverFromTypeInKnownDependentBase(Sema &S, |
| const IdentifierInfo &II, |
| SourceLocation NameLoc) { |
| // Lookup in the parent class template context, if any. |
| const CXXRecordDecl *RD = nullptr; |
| UnqualifiedTypeNameLookupResult FoundTypeDecl = |
| UnqualifiedTypeNameLookupResult::NotFound; |
| for (DeclContext *DC = S.CurContext; |
| DC && FoundTypeDecl == UnqualifiedTypeNameLookupResult::NotFound; |
| DC = DC->getParent()) { |
| // Look for type decls in dependent base classes that have known primary |
| // templates. |
| RD = dyn_cast<CXXRecordDecl>(DC); |
| if (RD && RD->getDescribedClassTemplate()) |
| FoundTypeDecl = lookupUnqualifiedTypeNameInBase(S, II, NameLoc, RD); |
| } |
| if (FoundTypeDecl != UnqualifiedTypeNameLookupResult::FoundType) |
| return nullptr; |
| |
| // We found some types in dependent base classes. Recover as if the user |
| // wrote 'typename MyClass::II' instead of 'II'. We'll fully resolve the |
| // lookup during template instantiation. |
| S.Diag(NameLoc, diag::ext_found_in_dependent_base) << &II; |
| |
| ASTContext &Context = S.Context; |
| auto *NNS = NestedNameSpecifier::Create(Context, nullptr, false, |
| cast<Type>(Context.getRecordType(RD))); |
| QualType T = Context.getDependentNameType(ETK_Typename, NNS, &II); |
| |
| CXXScopeSpec SS; |
| SS.MakeTrivial(Context, NNS, SourceRange(NameLoc)); |
| |
| TypeLocBuilder Builder; |
| DependentNameTypeLoc DepTL = Builder.push<DependentNameTypeLoc>(T); |
| DepTL.setNameLoc(NameLoc); |
| DepTL.setElaboratedKeywordLoc(SourceLocation()); |
| DepTL.setQualifierLoc(SS.getWithLocInContext(Context)); |
| return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); |
| } |
| |
| /// If the identifier refers to a type name within this scope, |
| /// return the declaration of that type. |
| /// |
| /// This routine performs ordinary name lookup of the identifier II |
| /// within the given scope, with optional C++ scope specifier SS, to |
| /// determine whether the name refers to a type. If so, returns an |
| /// opaque pointer (actually a QualType) corresponding to that |
| /// type. Otherwise, returns NULL. |
| ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, |
| Scope *S, CXXScopeSpec *SS, |
| bool isClassName, bool HasTrailingDot, |
| ParsedType ObjectTypePtr, |
| bool IsCtorOrDtorName, |
| bool WantNontrivialTypeSourceInfo, |
| bool IsClassTemplateDeductionContext, |
| IdentifierInfo **CorrectedII) { |
| // FIXME: Consider allowing this outside C++1z mode as an extension. |
| bool AllowDeducedTemplate = IsClassTemplateDeductionContext && |
| getLangOpts().CPlusPlus17 && !IsCtorOrDtorName && |
| !isClassName && !HasTrailingDot; |
| |
| // Determine where we will perform name lookup. |
| DeclContext *LookupCtx = nullptr; |
| if (ObjectTypePtr) { |
| QualType ObjectType = ObjectTypePtr.get(); |
| if (ObjectType->isRecordType()) |
| LookupCtx = computeDeclContext(ObjectType); |
| } else if (SS && SS->isNotEmpty()) { |
| LookupCtx = computeDeclContext(*SS, false); |
| |
| if (!LookupCtx) { |
| if (isDependentScopeSpecifier(*SS)) { |
| // C++ [temp.res]p3: |
| // A qualified-id that refers to a type and in which the |
| // nested-name-specifier depends on a template-parameter (14.6.2) |
| // shall be prefixed by the keyword typename to indicate that the |
| // qualified-id denotes a type, forming an |
| // elaborated-type-specifier (7.1.5.3). |
| // |
| // We therefore do not perform any name lookup if the result would |
| // refer to a member of an unknown specialization. |
| if (!isClassName && !IsCtorOrDtorName) |
| return nullptr; |
| |
| // We know from the grammar that this name refers to a type, |
| // so build a dependent node to describe the type. |
| if (WantNontrivialTypeSourceInfo) |
| return ActOnTypenameType(S, SourceLocation(), *SS, II, NameLoc).get(); |
| |
| NestedNameSpecifierLoc QualifierLoc = SS->getWithLocInContext(Context); |
| QualType T = CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc, |
| II, NameLoc); |
| return ParsedType::make(T); |
| } |
| |
| return nullptr; |
| } |
| |
| if (!LookupCtx->isDependentContext() && |
| RequireCompleteDeclContext(*SS, LookupCtx)) |
| return nullptr; |
| } |
| |
| // FIXME: LookupNestedNameSpecifierName isn't the right kind of |
| // lookup for class-names. |
| LookupNameKind Kind = isClassName ? LookupNestedNameSpecifierName : |
| LookupOrdinaryName; |
| LookupResult Result(*this, &II, NameLoc, Kind); |
| if (LookupCtx) { |
| // Perform "qualified" name lookup into the declaration context we |
| // computed, which is either the type of the base of a member access |
| // expression or the declaration context associated with a prior |
| // nested-name-specifier. |
| LookupQualifiedName(Result, LookupCtx); |
| |
| if (ObjectTypePtr && Result.empty()) { |
| // C++ [basic.lookup.classref]p3: |
| // If the unqualified-id is ~type-name, the type-name is looked up |
| // in the context of the entire postfix-expression. If the type T of |
| // the object expression is of a class type C, the type-name is also |
| // looked up in the scope of class C. At least one of the lookups shall |
| // find a name that refers to (possibly cv-qualified) T. |
| LookupName(Result, S); |
| } |
| } else { |
| // Perform unqualified name lookup. |
| LookupName(Result, S); |
| |
| // For unqualified lookup in a class template in MSVC mode, look into |
| // dependent base classes where the primary class template is known. |
| if (Result.empty() && getLangOpts().MSVCCompat && (!SS || SS->isEmpty())) { |
| if (ParsedType TypeInBase = |
| recoverFromTypeInKnownDependentBase(*this, II, NameLoc)) |
| return TypeInBase; |
| } |
| } |
| |
| NamedDecl *IIDecl = nullptr; |
| switch (Result.getResultKind()) { |
| case LookupResult::NotFound: |
| case LookupResult::NotFoundInCurrentInstantiation: |
| if (CorrectedII) { |
| TypeNameValidatorCCC CCC(/*AllowInvalid=*/true, isClassName, |
| AllowDeducedTemplate); |
| TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(), Kind, |
| S, SS, CCC, CTK_ErrorRecovery); |
| IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo(); |
| TemplateTy Template; |
| bool MemberOfUnknownSpecialization; |
| UnqualifiedId TemplateName; |
| TemplateName.setIdentifier(NewII, NameLoc); |
| NestedNameSpecifier *NNS = Correction.getCorrectionSpecifier(); |
| CXXScopeSpec NewSS, *NewSSPtr = SS; |
| if (SS && NNS) { |
| NewSS.MakeTrivial(Context, NNS, SourceRange(NameLoc)); |
| NewSSPtr = &NewSS; |
| } |
| if (Correction && (NNS || NewII != &II) && |
| // Ignore a correction to a template type as the to-be-corrected |
| // identifier is not a template (typo correction for template names |
| // is handled elsewhere). |
| !(getLangOpts().CPlusPlus && NewSSPtr && |
| isTemplateName(S, *NewSSPtr, false, TemplateName, nullptr, false, |
| Template, MemberOfUnknownSpecialization))) { |
| ParsedType Ty = getTypeName(*NewII, NameLoc, S, NewSSPtr, |
| isClassName, HasTrailingDot, ObjectTypePtr, |
| IsCtorOrDtorName, |
| WantNontrivialTypeSourceInfo, |
| IsClassTemplateDeductionContext); |
| if (Ty) { |
| diagnoseTypo(Correction, |
| PDiag(diag::err_unknown_type_or_class_name_suggest) |
| << Result.getLookupName() << isClassName); |
| if (SS && NNS) |
| SS->MakeTrivial(Context, NNS, SourceRange(NameLoc)); |
| *CorrectedII = NewII; |
| return Ty; |
| } |
| } |
| } |
| // If typo correction failed or was not performed, fall through |
| LLVM_FALLTHROUGH; |
| case LookupResult::FoundOverloaded: |
| case LookupResult::FoundUnresolvedValue: |
| Result.suppressDiagnostics(); |
| return nullptr; |
| |
| case LookupResult::Ambiguous: |
| // Recover from type-hiding ambiguities by hiding the type. We'll |
| // do the lookup again when looking for an object, and we can |
| // diagnose the error then. If we don't do this, then the error |
| // about hiding the type will be immediately followed by an error |
| // that only makes sense if the identifier was treated like a type. |
| if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) { |
| Result.suppressDiagnostics(); |
| return nullptr; |
| } |
| |
| // Look to see if we have a type anywhere in the list of results. |
| for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end(); |
| Res != ResEnd; ++Res) { |
| NamedDecl *RealRes = (*Res)->getUnderlyingDecl(); |
| if (isa<TypeDecl, ObjCInterfaceDecl, UnresolvedUsingIfExistsDecl>( |
| RealRes) || |
| (AllowDeducedTemplate && getAsTypeTemplateDecl(RealRes))) { |
| if (!IIDecl || |
| // Make the selection of the recovery decl deterministic. |
| RealRes->getLocation() < IIDecl->getLocation()) |
| IIDecl = RealRes; |
| } |
| } |
| |
| if (!IIDecl) { |
| // None of the entities we found is a type, so there is no way |
| // to even assume that the result is a type. In this case, don't |
| // complain about the ambiguity. The parser will either try to |
| // perform this lookup again (e.g., as an object name), which |
| // will produce the ambiguity, or will complain that it expected |
| // a type name. |
| Result.suppressDiagnostics(); |
| return nullptr; |
| } |
| |
| // We found a type within the ambiguous lookup; diagnose the |
| // ambiguity and then return that type. This might be the right |
| // answer, or it might not be, but it suppresses any attempt to |
| // perform the name lookup again. |
| break; |
| |
| case LookupResult::Found: |
| IIDecl = Result.getFoundDecl(); |
| break; |
| } |
| |
| assert(IIDecl && "Didn't find decl"); |
| |
| QualType T; |
| if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) { |
| // C++ [class.qual]p2: A lookup that would find the injected-class-name |
| // instead names the constructors of the class, except when naming a class. |
| // This is ill-formed when we're not actually forming a ctor or dtor name. |
| auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx); |
| auto *FoundRD = dyn_cast<CXXRecordDecl>(TD); |
| if (!isClassName && !IsCtorOrDtorName && LookupRD && FoundRD && |
| FoundRD->isInjectedClassName() && |
| declaresSameEntity(LookupRD, cast<Decl>(FoundRD->getParent()))) |
| Diag(NameLoc, diag::err_out_of_line_qualified_id_type_names_constructor) |
| << &II << /*Type*/1; |
| |
| DiagnoseUseOfDecl(IIDecl, NameLoc); |
| |
| T = Context.getTypeDeclType(TD); |
| MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false); |
| } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { |
| (void)DiagnoseUseOfDecl(IDecl, NameLoc); |
| if (!HasTrailingDot) |
| T = Context.getObjCInterfaceType(IDecl); |
| } else if (auto *UD = dyn_cast<UnresolvedUsingIfExistsDecl>(IIDecl)) { |
| (void)DiagnoseUseOfDecl(UD, NameLoc); |
| // Recover with 'int' |
| T = Context.IntTy; |
| } else if (AllowDeducedTemplate) { |
| if (auto *TD = getAsTypeTemplateDecl(IIDecl)) |
| T = Context.getDeducedTemplateSpecializationType(TemplateName(TD), |
| QualType(), false); |
| } |
| |
| if (T.isNull()) { |
| // If it's not plausibly a type, suppress diagnostics. |
| Result.suppressDiagnostics(); |
| return nullptr; |
| } |
| |
| // NOTE: avoid constructing an ElaboratedType(Loc) if this is a |
| // constructor or destructor name (in such a case, the scope specifier |
| // will be attached to the enclosing Expr or Decl node). |
| if (SS && SS->isNotEmpty() && !IsCtorOrDtorName && |
| !isa<ObjCInterfaceDecl, UnresolvedUsingIfExistsDecl>(IIDecl)) { |
| if (WantNontrivialTypeSourceInfo) { |
| // Construct a type with type-source information. |
| TypeLocBuilder Builder; |
| Builder.pushTypeSpec(T).setNameLoc(NameLoc); |
| |
| T = getElaboratedType(ETK_None, *SS, T); |
| ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T); |
| ElabTL.setElaboratedKeywordLoc(SourceLocation()); |
| ElabTL.setQualifierLoc(SS->getWithLocInContext(Context)); |
| return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); |
| } else { |
| T = getElaboratedType(ETK_None, *SS, T); |
| } |
| } |
| |
| return ParsedType::make(T); |
| } |
| |
| // Builds a fake NNS for the given decl context. |
| static NestedNameSpecifier * |
| synthesizeCurrentNestedNameSpecifier(ASTContext &Context, DeclContext *DC) { |
| for (;; DC = DC->getLookupParent()) { |
| DC = DC->getPrimaryContext(); |
| auto *ND = dyn_cast<NamespaceDecl>(DC); |
| if (ND && !ND->isInline() && !ND->isAnonymousNamespace()) |
| return NestedNameSpecifier::Create(Context, nullptr, ND); |
| else if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) |
| return NestedNameSpecifier::Create(Context, nullptr, RD->isTemplateDecl(), |
| RD->getTypeForDecl()); |
| else if (isa<TranslationUnitDecl>(DC)) |
| return NestedNameSpecifier::GlobalSpecifier(Context); |
| } |
| llvm_unreachable("something isn't in TU scope?"); |
| } |
| |
| /// Find the parent class with dependent bases of the innermost enclosing method |
| /// context. Do not look for enclosing CXXRecordDecls directly, or we will end |
| /// up allowing unqualified dependent type names at class-level, which MSVC |
| /// correctly rejects. |
| static const CXXRecordDecl * |
| findRecordWithDependentBasesOfEnclosingMethod(const DeclContext *DC) { |
| for (; DC && DC->isDependentContext(); DC = DC->getLookupParent()) { |
| DC = DC->getPrimaryContext(); |
| if (const auto *MD = dyn_cast<CXXMethodDecl>(DC)) |
| if (MD->getParent()->hasAnyDependentBases()) |
| return MD->getParent(); |
| } |
| return nullptr; |
| } |
| |
| ParsedType Sema::ActOnMSVCUnknownTypeName(const IdentifierInfo &II, |
| SourceLocation NameLoc, |
| bool IsTemplateTypeArg) { |
| assert(getLangOpts().MSVCCompat && "shouldn't be called in non-MSVC mode"); |
| |
| NestedNameSpecifier *NNS = nullptr; |
| if (IsTemplateTypeArg && getCurScope()->isTemplateParamScope()) { |
| // If we weren't able to parse a default template argument, delay lookup |
| // until instantiation time by making a non-dependent DependentTypeName. We |
| // pretend we saw a NestedNameSpecifier referring to the current scope, and |
| // lookup is retried. |
| // FIXME: This hurts our diagnostic quality, since we get errors like "no |
| // type named 'Foo' in 'current_namespace'" when the user didn't write any |
| // name specifiers. |
| NNS = synthesizeCurrentNestedNameSpecifier(Context, CurContext); |
| Diag(NameLoc, diag::ext_ms_delayed_template_argument) << &II; |
| } else if (const CXXRecordDecl *RD = |
| findRecordWithDependentBasesOfEnclosingMethod(CurContext)) { |
| // Build a DependentNameType that will perform lookup into RD at |
| // instantiation time. |
| NNS = NestedNameSpecifier::Create(Context, nullptr, RD->isTemplateDecl(), |
| RD->getTypeForDecl()); |
| |
| // Diagnose that this identifier was undeclared, and retry the lookup during |
| // template instantiation. |
| Diag(NameLoc, diag::ext_undeclared_unqual_id_with_dependent_base) << &II |
| << RD; |
| } else { |
| // This is not a situation that we should recover from. |
| return ParsedType(); |
| } |
| |
| QualType T = Context.getDependentNameType(ETK_None, NNS, &II); |
| |
| // Build type location information. We synthesized the qualifier, so we have |
| // to build a fake NestedNameSpecifierLoc. |
| NestedNameSpecifierLocBuilder NNSLocBuilder; |
| NNSLocBuilder.MakeTrivial(Context, NNS, SourceRange(NameLoc)); |
| NestedNameSpecifierLoc QualifierLoc = NNSLocBuilder.getWithLocInContext(Context); |
| |
| TypeLocBuilder Builder; |
| DependentNameTypeLoc DepTL = Builder.push<DependentNameTypeLoc>(T); |
| DepTL.setNameLoc(NameLoc); |
| DepTL.setElaboratedKeywordLoc(SourceLocation()); |
| DepTL.setQualifierLoc(QualifierLoc); |
| return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); |
| } |
| |
| /// isTagName() - This method is called *for error recovery purposes only* |
| /// to determine if the specified name is a valid tag name ("struct foo"). If |
| /// so, this returns the TST for the tag corresponding to it (TST_enum, |
| /// TST_union, TST_struct, TST_interface, TST_class). This is used to diagnose |
| /// cases in C where the user forgot to specify the tag. |
| DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { |
| // Do a tag name lookup in this scope. |
| LookupResult R(*this, &II, SourceLocation(), LookupTagName); |
| LookupName(R, S, false); |
| R.suppressDiagnostics(); |
| if (R.getResultKind() == LookupResult::Found) |
| if (const TagDecl *TD = R.getAsSingle<TagDecl>()) { |
| switch (TD->getTagKind()) { |
| case TTK_Struct: return DeclSpec::TST_struct; |
| case TTK_Interface: return DeclSpec::TST_interface; |
| case TTK_Union: return DeclSpec::TST_union; |
| case TTK_Class: return DeclSpec::TST_class; |
| case TTK_Enum: return DeclSpec::TST_enum; |
| } |
| } |
| |
| return DeclSpec::TST_unspecified; |
| } |
| |
| /// isMicrosoftMissingTypename - In Microsoft mode, within class scope, |
| /// if a CXXScopeSpec's type is equal to the type of one of the base classes |
| /// then downgrade the missing typename error to a warning. |
| /// This is needed for MSVC compatibility; Example: |
| /// @code |
| /// template<class T> class A { |
| /// public: |
| /// typedef int TYPE; |
| /// }; |
| /// template<class T> class B : public A<T> { |
| /// public: |
| /// A<T>::TYPE a; // no typename required because A<T> is a base class. |
| /// }; |
| /// @endcode |
| bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) { |
| if (CurContext->isRecord()) { |
| if (SS->getScopeRep()->getKind() == NestedNameSpecifier::Super) |
| return true; |
| |
| const Type *Ty = SS->getScopeRep()->getAsType(); |
| |
| CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext); |
| for (const auto &Base : RD->bases()) |
| if (Ty && Context.hasSameUnqualifiedType(QualType(Ty, 1), Base.getType())) |
| return true; |
| return S->isFunctionPrototypeScope(); |
| } |
| return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope(); |
| } |
| |
| void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, |
| SourceLocation IILoc, |
| Scope *S, |
| CXXScopeSpec *SS, |
| ParsedType &SuggestedType, |
| bool IsTemplateName) { |
| // Don't report typename errors for editor placeholders. |
| if (II->isEditorPlaceholder()) |
| return; |
| // We don't have anything to suggest (yet). |
| SuggestedType = nullptr; |
| |
| // There may have been a typo in the name of the type. Look up typo |
| // results, in case we have something that we can suggest. |
| TypeNameValidatorCCC CCC(/*AllowInvalid=*/false, /*WantClass=*/false, |
| /*AllowTemplates=*/IsTemplateName, |
| /*AllowNonTemplates=*/!IsTemplateName); |
| if (TypoCorrection Corrected = |
| CorrectTypo(DeclarationNameInfo(II, IILoc), LookupOrdinaryName, S, SS, |
| CCC, CTK_ErrorRecovery)) { |
| // FIXME: Support error recovery for the template-name case. |
| bool CanRecover = !IsTemplateName; |
| if (Corrected.isKeyword()) { |
| // We corrected to a keyword. |
| diagnoseTypo(Corrected, |
| PDiag(IsTemplateName ? diag::err_no_template_suggest |
| : diag::err_unknown_typename_suggest) |
| << II); |
| II = Corrected.getCorrectionAsIdentifierInfo(); |
| } else { |
| // We found a similarly-named type or interface; suggest that. |
| if (!SS || !SS->isSet()) { |
| diagnoseTypo(Corrected, |
| PDiag(IsTemplateName ? diag::err_no_template_suggest |
| : diag::err_unknown_typename_suggest) |
| << II, CanRecover); |
| } else if (DeclContext *DC = computeDeclContext(*SS, false)) { |
| std::string CorrectedStr(Corrected.getAsString(getLangOpts())); |
| bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && |
| II->getName().equals(CorrectedStr); |
| diagnoseTypo(Corrected, |
| PDiag(IsTemplateName |
| ? diag::err_no_member_template_suggest |
| : diag::err_unknown_nested_typename_suggest) |
| << II << DC << DroppedSpecifier << SS->getRange(), |
| CanRecover); |
| } else { |
| llvm_unreachable("could not have corrected a typo here"); |
| } |
| |
| if (!CanRecover) |
| return; |
| |
| CXXScopeSpec tmpSS; |
| if (Corrected.getCorrectionSpecifier()) |
| tmpSS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(), |
| SourceRange(IILoc)); |
| // FIXME: Support class template argument deduction here. |
| SuggestedType = |
| getTypeName(*Corrected.getCorrectionAsIdentifierInfo(), IILoc, S, |
| tmpSS.isSet() ? &tmpSS : SS, false, false, nullptr, |
| /*IsCtorOrDtorName=*/false, |
| /*WantNontrivialTypeSourceInfo=*/true); |
| } |
| return; |
| } |
| |
| if (getLangOpts().CPlusPlus && !IsTemplateName) { |
| // See if II is a class template that the user forgot to pass arguments to. |
| UnqualifiedId Name; |
| Name.setIdentifier(II, IILoc); |
| CXXScopeSpec EmptySS; |
| TemplateTy TemplateResult; |
| bool MemberOfUnknownSpecialization; |
| if (isTemplateName(S, SS ? *SS : EmptySS, /*hasTemplateKeyword=*/false, |
| Name, nullptr, true, TemplateResult, |
| MemberOfUnknownSpecialization) == TNK_Type_template) { |
| diagnoseMissingTemplateArguments(TemplateResult.get(), IILoc); |
| return; |
| } |
| } |
| |
| // FIXME: Should we move the logic that tries to recover from a missing tag |
| // (struct, union, enum) from Parser::ParseImplicitInt here, instead? |
| |
| if (!SS || (!SS->isSet() && !SS->isInvalid())) |
| Diag(IILoc, IsTemplateName ? diag::err_no_template |
| : diag::err_unknown_typename) |
| << II; |
| else if (DeclContext *DC = computeDeclContext(*SS, false)) |
| Diag(IILoc, IsTemplateName ? diag::err_no_member_template |
| : diag::err_typename_nested_not_found) |
| << II << DC << SS->getRange(); |
| else if (SS->isValid() && SS->getScopeRep()->containsErrors()) { |
| SuggestedType = |
| ActOnTypenameType(S, SourceLocation(), *SS, *II, IILoc).get(); |
| } else if (isDependentScopeSpecifier(*SS)) { |
| unsigned DiagID = diag::err_typename_missing; |
| if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S)) |
| DiagID = diag::ext_typename_missing; |
| |
| Diag(SS->getRange().getBegin(), DiagID) |
| << SS->getScopeRep() << II->getName() |
| << SourceRange(SS->getRange().getBegin(), IILoc) |
| << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename "); |
| SuggestedType = ActOnTypenameType(S, SourceLocation(), |
| *SS, *II, IILoc).get(); |
| } else { |
| assert(SS && SS->isInvalid() && |
| "Invalid scope specifier has already been diagnosed"); |
| } |
| } |
| |
| /// Determine whether the given result set contains either a type name |
| /// or |
| static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) { |
| bool CheckTemplate = R.getSema().getLangOpts().CPlusPlus && |
| NextToken.is(tok::less); |
| |
| for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) { |
| if (isa<TypeDecl>(*I) || isa<ObjCInterfaceDecl>(*I)) |
| return true; |
| |
| if (CheckTemplate && isa<TemplateDecl>(*I)) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result, |
| Scope *S, CXXScopeSpec &SS, |
| IdentifierInfo *&Name, |
| SourceLocation NameLoc) { |
| LookupResult R(SemaRef, Name, NameLoc, Sema::LookupTagName); |
| SemaRef.LookupParsedName(R, S, &SS); |
| if (TagDecl *Tag = R.getAsSingle<TagDecl>()) { |
| StringRef FixItTagName; |
| switch (Tag->getTagKind()) { |
| case TTK_Class: |
| FixItTagName = "class "; |
| break; |
| |
| case TTK_Enum: |
| FixItTagName = "enum "; |
| break; |
| |
| case TTK_Struct: |
| FixItTagName = "struct "; |
| break; |
| |
| case TTK_Interface: |
| FixItTagName = "__interface "; |
| break; |
| |
| case TTK_Union: |
| FixItTagName = "union "; |
| break; |
| } |
| |
| StringRef TagName = FixItTagName.drop_back(); |
| SemaRef.Diag(NameLoc, diag::err_use_of_tag_name_without_tag) |
| << Name << TagName << SemaRef.getLangOpts().CPlusPlus |
| << FixItHint::CreateInsertion(NameLoc, FixItTagName); |
| |
| for (LookupResult::iterator I = Result.begin(), IEnd = Result.end(); |
| I != IEnd; ++I) |
| SemaRef.Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type) |
| << Name << TagName; |
| |
| // Replace lookup results with just the tag decl. |
| Result.clear(Sema::LookupTagName); |
| SemaRef.LookupParsedName(Result, S, &SS); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /// Build a ParsedType for a simple-type-specifier with a nested-name-specifier. |
| static ParsedType buildNestedType(Sema &S, CXXScopeSpec &SS, |
| QualType T, SourceLocation NameLoc) { |
| ASTContext &Context = S.Context; |
| |
| TypeLocBuilder Builder; |
| Builder.pushTypeSpec(T).setNameLoc(NameLoc); |
| |
| T = S.getElaboratedType(ETK_None, SS, T); |
| ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T); |
| ElabTL.setElaboratedKeywordLoc(SourceLocation()); |
| ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); |
| return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); |
| } |
| |
| Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, |
| IdentifierInfo *&Name, |
| SourceLocation NameLoc, |
| const Token &NextToken, |
| CorrectionCandidateCallback *CCC) { |
| DeclarationNameInfo NameInfo(Name, NameLoc); |
| ObjCMethodDecl *CurMethod = getCurMethodDecl(); |
| |
| assert(NextToken.isNot(tok::coloncolon) && |
| "parse nested name specifiers before calling ClassifyName"); |
| if (getLangOpts().CPlusPlus && SS.isSet() && |
| isCurrentClassName(*Name, S, &SS)) { |
| // Per [class.qual]p2, this names the constructors of SS, not the |
| // injected-class-name. We don't have a classification for that. |
| // There's not much point caching this result, since the parser |
| // will reject it later. |
| return NameClassification::Unknown(); |
| } |
| |
| LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); |
| LookupParsedName(Result, S, &SS, !CurMethod); |
| |
| if (SS.isInvalid()) |
| return NameClassification::Error(); |
| |
| // For unqualified lookup in a class template in MSVC mode, look into |
| // dependent base classes where the primary class template is known. |
| if (Result.empty() && SS.isEmpty() && getLangOpts().MSVCCompat) { |
| if (ParsedType TypeInBase = |
| recoverFromTypeInKnownDependentBase(*this, *Name, NameLoc)) |
| return TypeInBase; |
| } |
| |
| // Perform lookup for Objective-C instance variables (including automatically |
| // synthesized instance variables), if we're in an Objective-C method. |
| // FIXME: This lookup really, really needs to be folded in to the normal |
| // unqualified lookup mechanism. |
| if (SS.isEmpty() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) { |
| DeclResult Ivar = LookupIvarInObjCMethod(Result, S, Name); |
| if (Ivar.isInvalid()) |
| return NameClassification::Error(); |
| if (Ivar.isUsable()) |
| return NameClassification::NonType(cast<NamedDecl>(Ivar.get())); |
| |
| // We defer builtin creation until after ivar lookup inside ObjC methods. |
| if (Result.empty()) |
| LookupBuiltin(Result); |
| } |
| |
| bool SecondTry = false; |
| bool IsFilteredTemplateName = false; |
| |
| Corrected: |
| switch (Result.getResultKind()) { |
| case LookupResult::NotFound: |
| // If an unqualified-id is followed by a '(', then we have a function |
| // call. |
| if (SS.isEmpty() && NextToken.is(tok::l_paren)) { |
| // In C++, this is an ADL-only call. |
| // FIXME: Reference? |
| if (getLangOpts().CPlusPlus) |
| return NameClassification::UndeclaredNonType(); |
| |
| // C90 6.3.2.2: |
| // If the expression that precedes the parenthesized argument list in a |
| // function call consists solely of an identifier, and if no |
| // declaration is visible for this identifier, the identifier is |
| // implicitly declared exactly as if, in the innermost block containing |
| // the function call, the declaration |
| // |
| // extern int identifier (); |
| // |
| // appeared. |
| // |
| // We also allow this in C99 as an extension. |
| if (NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *Name, S)) |
| return NameClassification::NonType(D); |
| } |
| |
| if (getLangOpts().CPlusPlus20 && SS.isEmpty() && NextToken.is(tok::less)) { |
| // In C++20 onwards, this could be an ADL-only call to a function |
| // template, and we're required to assume that this is a template name. |
| // |
| // FIXME: Find a way to still do typo correction in this case. |
| TemplateName Template = |
| Context.getAssumedTemplateName(NameInfo.getName()); |
| return NameClassification::UndeclaredTemplate(Template); |
| } |
| |
| // In C, we first see whether there is a tag type by the same name, in |
| // which case it's likely that the user just forgot to write "enum", |
| // "struct", or "union". |
| if (!getLangOpts().CPlusPlus && !SecondTry && |
| isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) { |
| break; |
| } |
| |
| // Perform typo correction to determine if there is another name that is |
| // close to this name. |
| if (!SecondTry && CCC) { |
| SecondTry = true; |
| if (TypoCorrection Corrected = |
| CorrectTypo(Result.getLookupNameInfo(), Result.getLookupKind(), S, |
| &SS, *CCC, CTK_ErrorRecovery)) { |
| unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; |
| unsigned QualifiedDiag = diag::err_no_member_suggest; |
| |
| NamedDecl *FirstDecl = Corrected.getFoundDecl(); |
| NamedDecl *UnderlyingFirstDecl = Corrected.getCorrectionDecl(); |
| if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && |
| UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) { |
| UnqualifiedDiag = diag::err_no_template_suggest; |
| QualifiedDiag = diag::err_no_member_template_suggest; |
| } else if (UnderlyingFirstDecl && |
| (isa<TypeDecl>(UnderlyingFirstDecl) || |
| isa<ObjCInterfaceDecl>(UnderlyingFirstDecl) || |
| isa<ObjCCompatibleAliasDecl>(UnderlyingFirstDecl))) { |
| UnqualifiedDiag = diag::err_unknown_typename_suggest; |
| QualifiedDiag = diag::err_unknown_nested_typename_suggest; |
| } |
| |
| if (SS.isEmpty()) { |
| diagnoseTypo(Corrected, PDiag(UnqualifiedDiag) << Name); |
| } else {// FIXME: is this even reachable? Test it. |
| std::string CorrectedStr(Corrected.getAsString(getLangOpts())); |
| bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && |
| Name->getName().equals(CorrectedStr); |
| diagnoseTypo(Corrected, PDiag(QualifiedDiag) |
| << Name << computeDeclContext(SS, false) |
| << DroppedSpecifier << SS.getRange()); |
| } |
| |
| // Update the name, so that the caller has the new name. |
| Name = Corrected.getCorrectionAsIdentifierInfo(); |
| |
| // Typo correction corrected to a keyword. |
| if (Corrected.isKeyword()) |
| return Name; |
| |
| // Also update the LookupResult... |
| // FIXME: This should probably go away at some point |
| Result.clear(); |
| Result.setLookupName(Corrected.getCorrection()); |
| if (FirstDecl) |
| Result.addDecl(FirstDecl); |
| |
| // If we found an Objective-C instance variable, let |
| // LookupInObjCMethod build the appropriate expression to |
| // reference the ivar. |
| // FIXME: This is a gross hack. |
| if (ObjCIvarDecl *Ivar = Result.getAsSingle<ObjCIvarDecl>()) { |
| DeclResult R = |
| LookupIvarInObjCMethod(Result, S, Ivar->getIdentifier()); |
| if (R.isInvalid()) |
| return NameClassification::Error(); |
| if (R.isUsable()) |
| return NameClassification::NonType(Ivar); |
| } |
| |
| goto Corrected; |
| } |
| } |
| |
| // We failed to correct; just fall through and let the parser deal with it. |
| Result.suppressDiagnostics(); |
| return NameClassification::Unknown(); |
| |
| case LookupResult::NotFoundInCurrentInstantiation: { |
| // We performed name lookup into the current instantiation, and there were |
| // dependent bases, so we treat this result the same way as any other |
| // dependent nested-name-specifier. |
| |
| // C++ [temp.res]p2: |
| // A name used in a template declaration or definition and that is |
| // dependent on a template-parameter is assumed not to name a type |
| // unless the applicable name lookup finds a type name or the name is |
| // qualified by the keyword typename. |
| // |
| // FIXME: If the next token is '<', we might want to ask the parser to |
| // perform some heroics to see if we actually have a |
| // template-argument-list, which would indicate a missing 'template' |
| // keyword here. |
| return NameClassification::DependentNonType(); |
| } |
| |
| case LookupResult::Found: |
| case LookupResult::FoundOverloaded: |
| case LookupResult::FoundUnresolvedValue: |
| break; |
| |
| case LookupResult::Ambiguous: |
| if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && |
| hasAnyAcceptableTemplateNames(Result, /*AllowFunctionTemplates=*/true, |
| /*AllowDependent=*/false)) { |
| // C++ [temp.local]p3: |
| // A lookup that finds an injected-class-name (10.2) can result in an |
| // ambiguity in certain cases (for example, if it is found in more than |
| // one base class). If all of the injected-class-names that are found |
| // refer to specializations of the same class template, and if the name |
| // is followed by a template-argument-list, the reference refers to the |
| // class template itself and not a specialization thereof, and is not |
| // ambiguous. |
| // |
| // This filtering can make an ambiguous result into an unambiguous one, |
| // so try again after filtering out template names. |
| FilterAcceptableTemplateNames(Result); |
| if (!Result.isAmbiguous()) { |
| IsFilteredTemplateName = true; |
| break; |
| } |
| } |
| |
| // Diagnose the ambiguity and return an error. |
| return NameClassification::Error(); |
| } |
| |
| if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && |
| (IsFilteredTemplateName || |
| hasAnyAcceptableTemplateNames( |
| Result, /*AllowFunctionTemplates=*/true, |
| /*AllowDependent=*/false, |
| /*AllowNonTemplateFunctions*/ SS.isEmpty() && |
| getLangOpts().CPlusPlus20))) { |
| // C++ [temp.names]p3: |
| // After name lookup (3.4) finds that a name is a template-name or that |
| // an operator-function-id or a literal- operator-id refers to a set of |
| // overloaded functions any member of which is a function template if |
| // this is followed by a <, the < is always taken as the delimiter of a |
| // template-argument-list and never as the less-than operator. |
| // C++2a [temp.names]p2: |
| // A name is also considered to refer to a template if it is an |
| // unqualified-id followed by a < and name lookup finds either one |
| // or more functions or finds nothing. |
| if (!IsFilteredTemplateName) |
| FilterAcceptableTemplateNames(Result); |
| |
| bool IsFunctionTemplate; |
| bool IsVarTemplate; |
| TemplateName Template; |
| if (Result.end() - Result.begin() > 1) { |
| IsFunctionTemplate = true; |
| Template = Context.getOverloadedTemplateName(Result.begin(), |
| Result.end()); |
| } else if (!Result.empty()) { |
| auto *TD = cast<TemplateDecl>(getAsTemplateNameDecl( |
| *Result.begin(), /*AllowFunctionTemplates=*/true, |
| /*AllowDependent=*/false)); |
| IsFunctionTemplate = isa<FunctionTemplateDecl>(TD); |
| IsVarTemplate = isa<VarTemplateDecl>(TD); |
| |
| if (SS.isNotEmpty()) |
| Template = |
| Context.getQualifiedTemplateName(SS.getScopeRep(), |
| /*TemplateKeyword=*/false, TD); |
| else |
| Template = TemplateName(TD); |
| } else { |
| // All results were non-template functions. This is a function template |
| // name. |
| IsFunctionTemplate = true; |
| Template = Context.getAssumedTemplateName(NameInfo.getName()); |
| } |
| |
| if (IsFunctionTemplate) { |
| // Function templates always go through overload resolution, at which |
| // point we'll perform the various checks (e.g., accessibility) we need |
| // to based on which function we selected. |
| Result.suppressDiagnostics(); |
| |
| return NameClassification::FunctionTemplate(Template); |
| } |
| |
| return IsVarTemplate ? NameClassification::VarTemplate(Template) |
| : NameClassification::TypeTemplate(Template); |
| } |
| |
| NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl(); |
| if (TypeDecl *Type = dyn_cast<TypeDecl>(FirstDecl)) { |
| DiagnoseUseOfDecl(Type, NameLoc); |
| MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false); |
| QualType T = Context.getTypeDeclType(Type); |
| if (SS.isNotEmpty()) |
| return buildNestedType(*this, SS, T, NameLoc); |
| return ParsedType::make(T); |
| } |
| |
| ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(FirstDecl); |
| if (!Class) { |
| // FIXME: It's unfortunate that we don't have a Type node for handling this. |
| if (ObjCCompatibleAliasDecl *Alias = |
| dyn_cast<ObjCCompatibleAliasDecl>(FirstDecl)) |
| Class = Alias->getClassInterface(); |
| } |
| |
| if (Class) { |
| DiagnoseUseOfDecl(Class, NameLoc); |
| |
| if (NextToken.is(tok::period)) { |
| // Interface. <something> is parsed as a property reference expression. |
| // Just return "unknown" as a fall-through for now. |
| Result.suppressDiagnostics(); |
| return NameClassification::Unknown(); |
| } |
| |
| QualType T = Context.getObjCInterfaceType(Class); |
| return ParsedType::make(T); |
| } |
| |
| if (isa<ConceptDecl>(FirstDecl)) |
| return NameClassification::Concept( |
| TemplateName(cast<TemplateDecl>(FirstDecl))); |
| |
| if (auto *EmptyD = dyn_cast<UnresolvedUsingIfExistsDecl>(FirstDecl)) { |
| (void)DiagnoseUseOfDecl(EmptyD, NameLoc); |
| return NameClassification::Error(); |
| } |
| |
| // We can have a type template here if we're classifying a template argument. |
| if (isa<TemplateDecl>(FirstDecl) && !isa<FunctionTemplateDecl>(FirstDecl) && |
| !isa<VarTemplateDecl>(FirstDecl)) |
| return NameClassification::TypeTemplate( |
| TemplateName(cast<TemplateDecl>(FirstDecl))); |
| |
| // Check for a tag type hidden by a non-type decl in a few cases where it |
| // seems likely a type is wanted instead of the non-type that was found. |
| bool NextIsOp = NextToken.isOneOf(tok::amp, tok::star); |
| if ((NextToken.is(tok::identifier) || |
| (NextIsOp && |
| FirstDecl->getUnderlyingDecl()->isFunctionOrFunctionTemplate())) && |
| isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) { |
| TypeDecl *Type = Result.getAsSingle<TypeDecl>(); |
| DiagnoseUseOfDecl(Type, NameLoc); |
| QualType T = Context.getTypeDeclType(Type); |
| if (SS.isNotEmpty()) |
| return buildNestedType(*this, SS, T, NameLoc); |
| return ParsedType::make(T); |
| } |
| |
| // If we already know which single declaration is referenced, just annotate |
| // that declaration directly. Defer resolving even non-overloaded class |
| // member accesses, as we need to defer certain access checks until we know |
| // the context. |
| bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren)); |
| if (Result.isSingleResult() && !ADL && !FirstDecl->isCXXClassMember()) |
| return NameClassification::NonType(Result.getRepresentativeDecl()); |
| |
| // Otherwise, this is an overload set that we will need to resolve later. |
| Result.suppressDiagnostics(); |
| return NameClassification::OverloadSet(UnresolvedLookupExpr::Create( |
| Context, Result.getNamingClass(), SS.getWithLocInContext(Context), |
| Result.getLookupNameInfo(), ADL, Result.isOverloadedResult(), |
| Result.begin(), Result.end())); |
| } |
| |
| ExprResult |
| Sema::ActOnNameClassifiedAsUndeclaredNonType(IdentifierInfo *Name, |
| SourceLocation NameLoc) { |
| assert(getLangOpts().CPlusPlus && "ADL-only call in C?"); |
| CXXScopeSpec SS; |
| LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); |
| return BuildDeclarationNameExpr(SS, Result, /*ADL=*/true); |
| } |
| |
| ExprResult |
| Sema::ActOnNameClassifiedAsDependentNonType(const CXXScopeSpec &SS, |
| IdentifierInfo *Name, |
| SourceLocation NameLoc, |
| bool IsAddressOfOperand) { |
| DeclarationNameInfo NameInfo(Name, NameLoc); |
| return ActOnDependentIdExpression(SS, /*TemplateKWLoc=*/SourceLocation(), |
| NameInfo, IsAddressOfOperand, |
| /*TemplateArgs=*/nullptr); |
| } |
| |
| ExprResult Sema::ActOnNameClassifiedAsNonType(Scope *S, const CXXScopeSpec &SS, |
| NamedDecl *Found, |
| SourceLocation NameLoc, |
| const Token &NextToken) { |
| if (getCurMethodDecl() && SS.isEmpty()) |
| if (auto *Ivar = dyn_cast<ObjCIvarDecl>(Found->getUnderlyingDecl())) |
| return BuildIvarRefExpr(S, NameLoc, Ivar); |
| |
| // Reconstruct the lookup result. |
| LookupResult Result(*this, Found->getDeclName(), NameLoc, LookupOrdinaryName); |
| Result.addDecl(Found); |
| Result.resolveKind(); |
| |
| bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren)); |
| return BuildDeclarationNameExpr(SS, Result, ADL); |
| } |
| |
| ExprResult Sema::ActOnNameClassifiedAsOverloadSet(Scope *S, Expr *E) { |
| // For an implicit class member access, transform the result into a member |
| // access expression if necessary. |
| auto *ULE = cast<UnresolvedLookupExpr>(E); |
| if ((*ULE->decls_begin())->isCXXClassMember()) { |
| CXXScopeSpec SS; |
| SS.Adopt(ULE->getQualifierLoc()); |
| |
| // Reconstruct the lookup result. |
| LookupResult Result(*this, ULE->getName(), ULE->getNameLoc(), |
| LookupOrdinaryName); |
| Result.setNamingClass(ULE->getNamingClass()); |
| for (auto I = ULE->decls_begin(), E = ULE->decls_end(); I != E; ++I) |
| Result.addDecl(*I, I.getAccess()); |
| Result.resolveKind(); |
| return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, |
| nullptr, S); |
| } |
| |
| // Otherwise, this is already in the form we needed, and no further checks |
| // are necessary. |
| return ULE; |
| } |
| |
| Sema::TemplateNameKindForDiagnostics |
| Sema::getTemplateNameKindForDiagnostics(TemplateName Name) { |
| auto *TD = Name.getAsTemplateDecl(); |
| if (!TD) |
| return TemplateNameKindForDiagnostics::DependentTemplate; |
| if (isa<ClassTemplateDecl>(TD)) |
| return TemplateNameKindForDiagnostics::ClassTemplate; |
| if (isa<FunctionTemplateDecl>(TD)) |
| return TemplateNameKindForDiagnostics::FunctionTemplate; |
| if (isa<VarTemplateDecl>(TD)) |
| return TemplateNameKindForDiagnostics::VarTemplate; |
| if (isa<TypeAliasTemplateDecl>(TD)) |
| return TemplateNameKindForDiagnostics::AliasTemplate; |
| if (isa<TemplateTemplateParmDecl>(TD)) |
| return TemplateNameKindForDiagnostics::TemplateTemplateParam; |
| if (isa<ConceptDecl>(TD)) |
| return TemplateNameKindForDiagnostics::Concept; |
| return TemplateNameKindForDiagnostics::DependentTemplate; |
| } |
| |
| void Sema::PushDeclContext(Scope *S, DeclContext *DC) { |
| assert(DC->getLexicalParent() == CurContext && |
| "The next DeclContext should be lexically contained in the current one."); |
| CurContext = DC; |
| S->setEntity(DC); |
| } |
| |
| void Sema::PopDeclContext() { |
| assert(CurContext && "DeclContext imbalance!"); |
| |
| CurContext = CurContext->getLexicalParent(); |
| assert(CurContext && "Popped translation unit!"); |
| } |
| |
| Sema::SkippedDefinitionContext Sema::ActOnTagStartSkippedDefinition(Scope *S, |
| Decl *D) { |
| // Unlike PushDeclContext, the context to which we return is not necessarily |
| // the containing DC of TD, because the new context will be some pre-existing |
| // TagDecl definition instead of a fresh one. |
| auto Result = static_cast<SkippedDefinitionContext>(CurContext); |
| CurContext = cast<TagDecl>(D)->getDefinition(); |
| assert(CurContext && "skipping definition of undefined tag"); |
| // Start lookups from the parent of the current context; we don't want to look |
| // into the pre-existing complete definition. |
| S->setEntity(CurContext->getLookupParent()); |
| return Result; |
| } |
| |
| void Sema::ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context) { |
| CurContext = static_cast<decltype(CurContext)>(Context); |
| } |
| |
| /// EnterDeclaratorContext - Used when we must lookup names in the context |
| /// of a declarator's nested name specifier. |
| /// |
| void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) { |
| // C++0x [basic.lookup.unqual]p13: |
| // A name used in the definition of a static data member of class |
| // X (after the qualified-id of the static member) is looked up as |
| // if the name was used in a member function of X. |
| // C++0x [basic.lookup.unqual]p14: |
| // If a variable member of a namespace is defined outside of the |
| // scope of its namespace then any name used in the definition of |
| // the variable member (after the declarator-id) is looked up as |
| // if the definition of the variable member occurred in its |
| // namespace. |
| // Both of these imply that we should push a scope whose context |
| // is the semantic context of the declaration. We can't use |
| // PushDeclContext here because that context is not necessarily |
| // lexically contained in the current context. Fortunately, |
| // the containing scope should have the appropriate information. |
| |
| assert(!S->getEntity() && "scope already has entity"); |
| |
| #ifndef NDEBUG |
| Scope *Ancestor = S->getParent(); |
| while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent(); |
| assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch"); |
| #endif |
| |
| CurContext = DC; |
| S->setEntity(DC); |
| |
| if (S->getParent()->isTemplateParamScope()) { |
| // Also set the corresponding entities for all immediately-enclosing |
| // template parameter scopes. |
| EnterTemplatedContext(S->getParent(), DC); |
| } |
| } |
| |
| void Sema::ExitDeclaratorContext(Scope *S) { |
| assert(S->getEntity() == CurContext && "Context imbalance!"); |
| |
| // Switch back to the lexical context. The safety of this is |
| // enforced by an assert in EnterDeclaratorContext. |
| Scope *Ancestor = S->getParent(); |
| while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent(); |
| CurContext = Ancestor->getEntity(); |
| |
| // We don't need to do anything with the scope, which is going to |
| // disappear. |
| } |
| |
| void Sema::EnterTemplatedContext(Scope *S, DeclContext *DC) { |
| assert(S->isTemplateParamScope() && |
| "expected to be initializing a template parameter scope"); |
| |
| // C++20 [temp.local]p7: |
| // In the definition of a member of a class template that appears outside |
| // of the class template definition, the name of a member of the class |
| // template hides the name of a template-parameter of any enclosing class |
| // templates (but not a template-parameter of the member if the member is a |
| // class or function template). |
| // C++20 [temp.local]p9: |
| // In the definition of a class template or in the definition of a member |
| // of such a template that appears outside of the template definition, for |
| // each non-dependent base class (13.8.2.1), if the name of the base class |
| // or the name of a member of the base class is the same as the name of a |
| // template-parameter, the base class name or member name hides the |
| // template-parameter name (6.4.10). |
| // |
| // This means that a template parameter scope should be searched immediately |
| // after searching the DeclContext for which it is a template parameter |
| // scope. For example, for |
| // template<typename T> template<typename U> template<typename V> |
| // void N::A<T>::B<U>::f(...) |
| // we search V then B<U> (and base classes) then U then A<T> (and base |
| // classes) then T then N then ::. |
| unsigned ScopeDepth = getTemplateDepth(S); |
| for (; S && S->isTemplateParamScope(); S = S->getParent(), --ScopeDepth) { |
| DeclContext *SearchDCAfterScope = DC; |
| for (; DC; DC = DC->getLookupParent()) { |
| if (const TemplateParameterList *TPL = |
| cast<Decl>(DC)->getDescribedTemplateParams()) { |
| unsigned DCDepth = TPL->getDepth() + 1; |
| if (DCDepth > ScopeDepth) |
| continue; |
| if (ScopeDepth == DCDepth) |
| SearchDCAfterScope = DC = DC->getLookupParent(); |
| break; |
| } |
| } |
| S->setLookupEntity(SearchDCAfterScope); |
| } |
| } |
| |
| void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) { |
| // We assume that the caller has already called |
| // ActOnReenterTemplateScope so getTemplatedDecl() works. |
| FunctionDecl *FD = D->getAsFunction(); |
| if (!FD) |
| return; |
| |
| // Same implementation as PushDeclContext, but enters the context |
| // from the lexical parent, rather than the top-level class. |
| assert(CurContext == FD->getLexicalParent() && |
| "The next DeclContext should be lexically contained in the current one."); |
| CurContext = FD; |
| S->setEntity(CurContext); |
| |
| for (unsigned P = 0, NumParams = FD->getNumParams(); P < NumParams; ++P) { |
| ParmVarDecl *Param = FD->getParamDecl(P); |
| // If the parameter has an identifier, then add it to the scope |
| if (Param->getIdentifier()) { |
| S->AddDecl(Param); |
| IdResolver.AddDecl(Param); |
| } |
| } |
| } |
| |
| void Sema::ActOnExitFunctionContext() { |
| // Same implementation as PopDeclContext, but returns to the lexical parent, |
| // rather than the top-level class. |
| assert(CurContext && "DeclContext imbalance!"); |
| CurContext = CurContext->getLexicalParent(); |
| assert(CurContext && "Popped translation unit!"); |
| } |
| |
| /// Determine whether we allow overloading of the function |
| /// PrevDecl with another declaration. |
| /// |
| /// This routine determines whether overloading is possible, not |
| /// whether some new function is actually an overload. It will return |
| /// true in C++ (where we can always provide overloads) or, as an |
| /// extension, in C when the previous function is already an |
| /// overloaded function declaration or has the "overloadable" |
| /// attribute. |
| static bool AllowOverloadingOfFunction(LookupResult &Previous, |
| ASTContext &Context, |
| const FunctionDecl *New) { |
| if (Context.getLangOpts().CPlusPlus) |
| return true; |
| |
| if (Previous.getResultKind() == LookupResult::FoundOverloaded) |
| return true; |
| |
| return Previous.getResultKind() == LookupResult::Found && |
| (Previous.getFoundDecl()->hasAttr<OverloadableAttr>() || |
| New->hasAttr<OverloadableAttr>()); |
| } |
| |
| /// Add this decl to the scope shadowed decl chains. |
| void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { |
| // Move up the scope chain until we find the nearest enclosing |
| // non-transparent context. The declaration will be introduced into this |
| // scope. |
| while (S->getEntity() && S->getEntity()->isTransparentContext()) |
| S = S->getParent(); |
| |
| // Add scoped declarations into their context, so that they can be |
| // found later. Declarations without a context won't be inserted |
| // into any context. |
| if (AddToContext) |
| CurContext->addDecl(D); |
| |
| // Out-of-line definitions shouldn't be pushed into scope in C++, unless they |
| // are function-local declarations. |
| if (getLangOpts().CPlusPlus && D->isOutOfLine() && !S->getFnParent()) |
| return; |
| |
| // Template instantiations should also not be pushed into scope. |
| if (isa<FunctionDecl>(D) && |
| cast<FunctionDecl>(D)->isFunctionTemplateSpecialization()) |
| return; |
| |
| // If this replaces anything in the current scope, |
| IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()), |
| IEnd = IdResolver.end(); |
| for (; I != IEnd; ++I) { |
| if (S->isDeclScope(*I) && D->declarationReplaces(*I)) { |
| S->RemoveDecl(*I); |
| IdResolver.RemoveDecl(*I); |
| |
| // Should only need to replace one decl. |
| break; |
| } |
| } |
| |
| S->AddDecl(D); |
| |
| if (isa<LabelDecl>(D) && !cast<LabelDecl>(D)->isGnuLocal()) { |
| // Implicitly-generated labels may end up getting generated in an order that |
| // isn't strictly lexical, which breaks name lookup. Be careful to insert |
| // the label at the appropriate place in the identifier chain. |
| for (I = IdResolver.begin(D->getDeclName()); I != IEnd; ++I) { |
| DeclContext *IDC = (*I)->getLexicalDeclContext()->getRedeclContext(); |
| if (IDC == CurContext) { |
| if (!S->isDeclScope(*I)) |
| continue; |
| } else if (IDC->Encloses(CurContext)) |
| break; |
| } |
| |
| IdResolver.InsertDeclAfter(I, D); |
| } else { |
| IdResolver.AddDecl(D); |
| } |
| warnOnReservedIdentifier(D); |
| } |
| |
| bool Sema::isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S, |
| bool AllowInlineNamespace) { |
| return IdResolver.isDeclInScope(D, Ctx, S, AllowInlineNamespace); |
| } |
| |
| Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) { |
| DeclContext *TargetDC = DC->getPrimaryContext(); |
| do { |
| if (DeclContext *ScopeDC = S->getEntity()) |
| if (ScopeDC->getPrimaryContext() == TargetDC) |
| return S; |
| } while ((S = S->getParent())); |
| |
| return nullptr; |
| } |
| |
| static bool isOutOfScopePreviousDeclaration(NamedDecl *, |
| DeclContext*, |
| ASTContext&); |
| |
| /// Filters out lookup results that don't fall within the given scope |
| /// as determined by isDeclInScope. |
| void Sema::FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, |
| bool ConsiderLinkage, |
| bool AllowInlineNamespace) { |
| LookupResult::Filter F = R.makeFilter(); |
| while (F.hasNext()) { |
| NamedDecl *D = F.next(); |
| |
| if (isDeclInScope(D, Ctx, S, AllowInlineNamespace)) |
| continue; |
| |
| if (ConsiderLinkage && isOutOfScopePreviousDeclaration(D, Ctx, Context)) |
| continue; |
| |
| F.erase(); |
| } |
| |
| F.done(); |
| } |
| |
| /// We've determined that \p New is a redeclaration of \p Old. Check that they |
| /// have compatible owning modules. |
| bool Sema::CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old) { |
| // FIXME: The Modules TS is not clear about how friend declarations are |
| // to be treated. It's not meaningful to have different owning modules for |
| // linkage in redeclarations of the same entity, so for now allow the |
| // redeclaration and change the owning modules to match. |
| if (New->getFriendObjectKind() && |
| Old->getOwningModuleForLinkage() != New->getOwningModuleForLinkage()) { |
| New->setLocalOwningModule(Old->getOwningModule()); |
| makeMergedDefinitionVisible(New); |
| return false; |
| } |
| |
| Module *NewM = New->getOwningModule(); |
| Module *OldM = Old->getOwningModule(); |
| |
| if (NewM && NewM->Kind == Module::PrivateModuleFragment) |
| NewM = NewM->Parent; |
| if (OldM && OldM->Kind == Module::PrivateModuleFragment) |
| OldM = OldM->Parent; |
| |
| if (NewM == OldM) |
| return false; |
| |
| bool NewIsModuleInterface = NewM && NewM->isModulePurview(); |
| bool OldIsModuleInterface = OldM && OldM->isModulePurview(); |
| if (NewIsModuleInterface || OldIsModuleInterface) { |
| // C++ Modules TS [basic.def.odr] 6.2/6.7 [sic]: |
| // if a declaration of D [...] appears in the purview of a module, all |
| // other such declarations shall appear in the purview of the same module |
| Diag(New->getLocation(), diag::err_mismatched_owning_module) |
| << New |
| << NewIsModuleInterface |
| << (NewIsModuleInterface ? NewM->getFullModuleName() : "") |
| << OldIsModuleInterface |
| << (OldIsModuleInterface ? OldM->getFullModuleName() : ""); |
| Diag(Old->getLocation(), diag::note_previous_declaration); |
| New->setInvalidDecl(); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| static bool isUsingDecl(NamedDecl *D) { |
| return isa<UsingShadowDecl>(D) || |
| isa<UnresolvedUsingTypenameDecl>(D) || |
| isa<UnresolvedUsingValueDecl>(D); |
| } |
| |
| /// Removes using shadow declarations from the lookup results. |
| static void RemoveUsingDecls(LookupResult &R) { |
| LookupResult::Filter F = R.makeFilter(); |
| while (F.hasNext()) |
| if (isUsingDecl(F.next())) |
| F.erase(); |
| |
| F.done(); |
| } |
| |
| /// Check for this common pattern: |
| /// @code |
| /// class S { |
| /// S(const S&); // DO NOT IMPLEMENT |
| /// void operator=(const S&); // DO NOT IMPLEMENT |
| /// }; |
| /// @endcode |
| static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) { |
| // FIXME: Should check for private access too but access is set after we get |
| // the decl here. |
| if (D->doesThisDeclarationHaveABody()) |
| return false; |
| |
| if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D)) |
| return CD->isCopyConstructor(); |
| return D->isCopyAssignmentOperator(); |
| } |
| |
| // We need this to handle |
| // |
| // typedef struct { |
| // void *foo() { return 0; } |
| // } A; |
| // |
| // When we see foo we don't know if after the typedef we will get 'A' or '*A' |
| // for example. If 'A', foo will have external linkage. If we have '*A', |
| // foo will have no linkage. Since we can't know until we get to the end |
| // of the typedef, this function finds out if D might have non-external linkage. |
| // Callers should verify at the end of the TU if it D has external linkage or |
| // not. |
| bool Sema::mightHaveNonExternalLinkage(const DeclaratorDecl *D) { |
| const DeclContext *DC = D->getDeclContext(); |
| while (!DC->isTranslationUnit()) { |
| if (const RecordDecl *RD = dyn_cast<RecordDecl>(DC)){ |
| if (!RD->hasNameForLinkage()) |
| return true; |
| } |
| DC = DC->getParent(); |
| } |
| |
| return !D->isExternallyVisible(); |
| } |
| |
| // FIXME: This needs to be refactored; some other isInMainFile users want |
| // these semantics. |
| static bool isMainFileLoc(const Sema &S, SourceLocation Loc) { |
| if (S.TUKind != TU_Complete) |
| return false; |
| return S.SourceMgr.isInMainFile(Loc); |
| } |
| |
| bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const { |
| assert(D); |
| |
| if (D->isInvalidDecl() || D->isUsed() || D->hasAttr<UnusedAttr>()) |
| return false; |
| |
| // Ignore all entities declared within templates, and out-of-line definitions |
| // of members of class templates. |
| if (D->getDeclContext()->isDependentContext() || |
| D->getLexicalDeclContext()->isDependentContext()) |
| return false; |
| |
| if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { |
| if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) |
| return false; |
| // A non-out-of-line declaration of a member specialization was implicitly |
| // instantiated; it's the out-of-line declaration that we're interested in. |
| if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization && |
| FD->getMemberSpecializationInfo() && !FD->isOutOfLine()) |
| return false; |
| |
| if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { |
| if (MD->isVirtual() || IsDisallowedCopyOrAssign(MD)) |
| return false; |
| } else { |
| // 'static inline' functions are defined in headers; don't warn. |
| if (FD->isInlined() && !isMainFileLoc(*this, FD->getLocation())) |
| return false; |
| } |
| |
| if (FD->doesThisDeclarationHaveABody() && |
| Context.DeclMustBeEmitted(FD)) |
| return false; |
| } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { |
| // Constants and utility variables are defined in headers with internal |
| // linkage; don't warn. (Unlike functions, there isn't a convenient marker |
| // like "inline".) |
| if (!isMainFileLoc(*this, VD->getLocation())) |
| return false; |
| |
| if (Context.DeclMustBeEmitted(VD)) |
| return false; |
| |
| if (VD->isStaticDataMember() && |
| VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) |
| return false; |
| if (VD->isStaticDataMember() && |
| VD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization && |
| VD->getMemberSpecializationInfo() && !VD->isOutOfLine()) |
| return false; |
| |
| if (VD->isInline() && !isMainFileLoc(*this, VD->getLocation())) |
| return false; |
| } else { |
| return false; |
| } |
| |
| // Only warn for unused decls internal to the translation unit. |
| // FIXME: This seems like a bogus check; it suppresses -Wunused-function |
| // for inline functions defined in the main source file, for instance. |
| return mightHaveNonExternalLinkage(D); |
| } |
| |
| void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) { |
| if (!D) |
| return; |
| |
| if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { |
| const FunctionDecl *First = FD->getFirstDecl(); |
| if (FD != First && ShouldWarnIfUnusedFileScopedDecl(First)) |
| return; // First should already be in the vector. |
| } |
| |
| if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { |
| const VarDecl *First = VD->getFirstDecl(); |
| if (VD != First && ShouldWarnIfUnusedFileScopedDecl(First)) |
| return; // First should already be in the vector. |
| } |
| |
| if (ShouldWarnIfUnusedFileScopedDecl(D)) |
| UnusedFileScopedDecls.push_back(D); |
| } |
| |
| static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { |
| if (D->isInvalidDecl()) |
| return false; |
| |
| if (auto *DD = dyn_cast<DecompositionDecl>(D)) { |
| // For a decomposition declaration, warn if none of the bindings are |
| // referenced, instead of if the variable itself is referenced (which |
| // it is, by the bindings' expressions). |
| for (auto *BD : DD->bindings()) |
| if (BD->isReferenced()) |
| return false; |
| } else if (!D->getDeclName()) { |
| return false; |
| } else if (D->isReferenced() || D->isUsed()) { |
| return false; |
| } |
| |
| if (D->hasAttr<UnusedAttr>() || D->hasAttr<ObjCPreciseLifetimeAttr>()) |
| return false; |
| |
| if (isa<LabelDecl>(D)) |
| return true; |
| |
| // Except for labels, we only care about unused decls that are local to |
| // functions. |
| bool WithinFunction = D->getDeclContext()->isFunctionOrMethod(); |
| if (const auto *R = dyn_cast<CXXRecordDecl>(D->getDeclContext())) |
| // For dependent types, the diagnostic is deferred. |
| WithinFunction = |
| WithinFunction || (R->isLocalClass() && !R->isDependentType()); |
| if (!WithinFunction) |
| return false; |
| |
| if (isa<TypedefNameDecl>(D)) |
| return true; |
| |
| // White-list anything that isn't a local variable. |
| if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) |
| return false; |
| |
| // Types of valid local variables should be complete, so this should succeed. |
| if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { |
| |
| // White-list anything with an __attribute__((unused)) type. |
| const auto *Ty = VD->getType().getTypePtr(); |
| |
| // Only look at the outermost level of typedef. |
| if (const TypedefType *TT = Ty->getAs<TypedefType>()) { |
| if (TT->getDecl()->hasAttr<UnusedAttr>()) |
| return false; |
| } |
| |
| // If we failed to complete the type for some reason, or if the type is |
| // dependent, don't diagnose the variable. |
| if (Ty->isIncompleteType() || Ty->isDependentType()) |
| return false; |
| |
| // Look at the element type to ensure that the warning behaviour is |
| // consistent for both scalars and arrays. |
| Ty = Ty->getBaseElementTypeUnsafe(); |
| |
| if (const TagType *TT = Ty->getAs<TagType>()) { |
| const TagDecl *Tag = TT->getDecl(); |
| if (Tag->hasAttr<UnusedAttr>()) |
| return false; |
| |
| if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) { |
| if (!RD->hasTrivialDestructor() && !RD->hasAttr<WarnUnusedAttr>()) |
| return false; |
| |
| if (const Expr *Init = VD->getInit()) { |
| if (const ExprWithCleanups *Cleanups = |
| dyn_cast<ExprWithCleanups>(Init)) |
| Init = Cleanups->getSubExpr(); |
| const CXXConstructExpr *Construct = |
| dyn_cast<CXXConstructExpr>(Init); |
| if (Construct && !Construct->isElidable()) { |
| CXXConstructorDecl *CD = Construct->getConstructor(); |
| if (!CD->isTrivial() && !RD->hasAttr<WarnUnusedAttr>() && |
| (VD->getInit()->isValueDependent() || !VD->evaluateValue())) |
| return false; |
| } |
| |
| // Suppress the warning if we don't know how this is constructed, and |
| // it could possibly be non-trivial constructor. |
| if (Init->isTypeDependent()) |
| for (const CXXConstructorDecl *Ctor : RD->ctors()) |
| if (!Ctor->isTrivial()) |
| return false; |
| } |
| } |
| } |
| |
| // TODO: __attribute__((unused)) templates? |
| } |
| |
| return true; |
| } |
| |
| static void GenerateFixForUnusedDecl(const NamedDecl *D, ASTContext &Ctx, |
| FixItHint &Hint) { |
| if (isa<LabelDecl>(D)) { |
| SourceLocation AfterColon = Lexer::findLocationAfterToken( |
| D->getEndLoc(), tok::colon, Ctx.getSourceManager(), Ctx.getLangOpts(), |
| true); |
| if (AfterColon.isInvalid()) |
| return; |
| Hint = FixItHint::CreateRemoval( |
| CharSourceRange::getCharRange(D->getBeginLoc(), AfterColon)); |
| } |
| } |
| |
| void Sema::DiagnoseUnusedNestedTypedefs(const RecordDecl *D) { |
| if (D->getTypeForDecl()->isDependentType()) |
| return; |
| |
| for (auto *TmpD : D->decls()) { |
| if (const auto *T = dyn_cast<TypedefNameDecl>(TmpD)) |
| DiagnoseUnusedDecl(T); |
| else if(const auto *R = dyn_cast<RecordDecl>(TmpD)) |
| DiagnoseUnusedNestedTypedefs(R); |
| } |
| } |
| |
| /// DiagnoseUnusedDecl - Emit warnings about declarations that are not used |
| /// unless they are marked attr(unused). |
| void Sema::DiagnoseUnusedDecl(const NamedDecl *D) { |
| if (!ShouldDiagnoseUnusedDecl(D)) |
| return; |
| |
| if (auto *TD = dyn_cast<TypedefNameDecl>(D)) { |
| // typedefs can be referenced later on, so the diagnostics are emitted |
| // at end-of-translation-unit. |
| UnusedLocalTypedefNameCandidates.insert(TD); |
| return; |
| } |
| |
| FixItHint Hint; |
| GenerateFixForUnusedDecl(D, Context, Hint); |
| |
| unsigned DiagID; |
| if (isa<VarDecl>(D) && cast<VarDecl>(D)->isExceptionVariable()) |
| DiagID = diag::warn_unused_exception_param; |
| else if (isa<LabelDecl>(D)) |
| DiagID = diag::warn_unused_label; |
| else |
| DiagID = diag::warn_unused_variable; |
| |
| Diag(D->getLocation(), DiagID) << D << Hint; |
| } |
| |
| void Sema::DiagnoseUnusedButSetDecl(const VarDecl *VD) { |
| // If it's not referenced, it can't be set. If it has the Cleanup attribute, |
| // it's not really unused. |
| if (!VD->isReferenced() || !VD->getDeclName() || VD->hasAttr<UnusedAttr>() || |
| VD->hasAttr<CleanupAttr>()) |
| return; |
| |
| const auto *Ty = VD->getType().getTypePtr()->getBaseElementTypeUnsafe(); |
| |
| if (Ty->isReferenceType() || Ty->isDependentType()) |
| return; |
| |
| if (const TagType *TT = Ty->getAs<TagType>()) { |
| const TagDecl *Tag = TT->getDecl(); |
| if (Tag->hasAttr<UnusedAttr>()) |
| return; |
| // In C++, don't warn for record types that don't have WarnUnusedAttr, to |
| // mimic gcc's behavior. |
| if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) { |
| if (!RD->hasAttr<WarnUnusedAttr>()) |
| return; |
| } |
| } |
| |
| // Don't warn about __block Objective-C pointer variables, as they might |
| // be assigned in the block but not used elsewhere for the purpose of lifetime |
| // extension. |
| if (VD->hasAttr<BlocksAttr>() && Ty->isObjCObjectPointerType()) |
| return; |
| |
| auto iter = RefsMinusAssignments.find(VD); |
| if (iter == RefsMinusAssignments.end()) |
| return; |
| |
| assert(iter->getSecond() >= 0 && |
| "Found a negative number of references to a VarDecl"); |
| if (iter->getSecond() != 0) |
| return; |
| unsigned DiagID = isa<ParmVarDecl>(VD) ? diag::warn_unused_but_set_parameter |
| : diag::warn_unused_but_set_variable; |
| Diag(VD->getLocation(), DiagID) << VD; |
| } |
| |
| static void CheckPoppedLabel(LabelDecl *L, Sema &S) { |
| // Verify that we have no forward references left. If so, there was a goto |
| // or address of a label taken, but no definition of it. Label fwd |
| // definitions are indicated with a null substmt which is also not a resolved |
| // MS inline assembly label name. |
| bool Diagnose = false; |
| if (L->isMSAsmLabel()) |
| Diagnose = !L->isResolvedMSAsmLabel(); |
| else |
| Diagnose = L->getStmt() == nullptr; |
| if (Diagnose) |
| S.Diag(L->getLocation(), diag::err_undeclared_label_use) << L; |
| } |
| |
| void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { |
| S->mergeNRVOIntoParent(); |
| |
| if (S->decl_empty()) return; |
| assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) && |
| "Scope shouldn't contain decls!"); |
| |
| for (auto *TmpD : S->decls()) { |
| assert(TmpD && "This decl didn't get pushed??"); |
| |
| assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?"); |
| NamedDecl *D = cast<NamedDecl>(TmpD); |
| |
| // Diagnose unused variables in this scope. |
| if (!S->hasUnrecoverableErrorOccurred()) { |
| DiagnoseUnusedDecl(D); |
| if (const auto *RD = dyn_cast<RecordDecl>(D)) |
| DiagnoseUnusedNestedTypedefs(RD); |
| if (VarDecl *VD = dyn_cast<VarDecl>(D)) { |
| DiagnoseUnusedButSetDecl(VD); |
| RefsMinusAssignments.erase(VD); |
| } |
| } |
| |
| if (!D->getDeclName()) continue; |
| |
| // If this was a forward reference to a label, verify it was defined. |
| if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) |
| CheckPoppedLabel(LD, *this); |
| |
| // Remove this name from our lexical scope, and warn on it if we haven't |
| // already. |
| IdResolver.RemoveDecl(D); |
| auto ShadowI = ShadowingDecls.find(D); |
| if (ShadowI != ShadowingDecls.end()) { |
| if (const auto *FD = dyn_cast<FieldDecl>(ShadowI->second)) { |
| Diag(D->getLocation(), diag::warn_ctor_parm_shadows_field) |
| << D << FD << FD->getParent(); |
| Diag(FD->getLocation(), diag::note_previous_declaration); |
| } |
| ShadowingDecls.erase(ShadowI); |
| } |
| } |
| } |
| |
| /// Look for an Objective-C class in the translation unit. |
| /// |
| /// \param Id The name of the Objective-C class we're looking for. If |
| /// typo-correction fixes this name, the Id will be updated |
| /// to the fixed name. |
| /// |
| /// \param IdLoc The location of the name in the translation unit. |
| /// |
| /// \param DoTypoCorrection If true, this routine will attempt typo correction |
| /// if there is no class with the given name. |
| /// |
| /// \returns The declaration of the named Objective-C class, or NULL if the |
| /// class could not be found. |
| ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, |
| SourceLocation IdLoc, |
| bool DoTypoCorrection) { |
| // The third "scope" argument is 0 since we aren't enabling lazy built-in |
| // creation from this context. |
| NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName); |
| |
| if (!IDecl && DoTypoCorrection) { |
| // Perform typo correction at the given location, but only if we |
| // find an Objective-C class name. |
| DeclFilterCCC<ObjCInterfaceDecl> CCC{}; |
| if (TypoCorrection C = |
| CorrectTypo(DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName, |
| TUScope, nullptr, CCC, CTK_ErrorRecovery)) { |
| diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id); |
| IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>(); |
| Id = IDecl->getIdentifier(); |
| } |
| } |
| ObjCInterfaceDecl *Def = dyn_cast_or_null<ObjCInterfaceDecl>(IDecl); |
| // This routine must always return a class definition, if any. |
| if (Def && Def->getDefinition()) |
| Def = Def->getDefinition(); |
| return Def; |
| } |
| |
| /// getNonFieldDeclScope - Retrieves the innermost scope, starting |
| /// from S, where a non-field would be declared. This routine copes |
| /// with the difference between C and C++ scoping rules in structs and |
| /// unions. For example, the following code is well-formed in C but |
| /// ill-formed in C++: |
| /// @code |
| /// struct S6 { |
| /// enum { BAR } e; |
| /// }; |
| /// |
| /// void test_S6() { |
| /// struct S6 a; |
| /// a.e = BAR; |
| /// } |
| /// @endcode |
| /// For the declaration of BAR, this routine will return a different |
| /// scope. The scope S will be the scope of the unnamed enumeration |
| /// within S6. In C++, this routine will return the scope associated |
| /// with S6, because the enumeration's scope is a transparent |
| /// context but structures can contain non-field names. In C, this |
| /// routine will return the translation unit scope, since the |
| /// enumeration's scope is a transparent context and structures cannot |
| /// contain non-field names. |
| Scope *Sema::getNonFieldDeclScope(Scope *S) { |
| while (((S->getFlags() & Scope::DeclScope) == 0) || |
| (S->getEntity() && S->getEntity()->isTransparentContext()) || |
| (S->isClassScope() && !getLangOpts().CPlusPlus)) |
| S = S->getParent(); |
| return S; |
| } |
| |
| static StringRef getHeaderName(Builtin::Context &BuiltinInfo, unsigned ID, |
| ASTContext::GetBuiltinTypeError Error) { |
| switch (Error) { |
| case ASTContext::GE_None: |
| return ""; |
| case ASTContext::GE_Missing_type: |
| return BuiltinInfo.getHeaderName(ID); |
| case ASTContext::GE_Missing_stdio: |
| return "stdio.h"; |
| case ASTContext::GE_Missing_setjmp: |
| return "setjmp.h"; |
| case ASTContext::GE_Missing_ucontext: |
| return "ucontext.h"; |
| } |
| llvm_unreachable("unhandled error kind"); |
| } |
| |
| FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, QualType Type, |
| unsigned ID, SourceLocation Loc) { |
| DeclContext *Parent = Context.getTranslationUnitDecl(); |
| |
| if (getLangOpts().CPlusPlus) { |
| LinkageSpecDecl *CLinkageDecl = LinkageSpecDecl::Create( |
| Context, Parent, Loc, Loc, LinkageSpecDecl::lang_c, false); |
| CLinkageDecl->setImplicit(); |
| Parent->addDecl(CLinkageDecl); |
| Parent = CLinkageDecl; |
| } |
| |
| FunctionDecl *New = FunctionDecl::Create(Context, Parent, Loc, Loc, II, Type, |
| /*TInfo=*/nullptr, SC_Extern, |
| getCurFPFeatures().isFPConstrained(), |
| false, Type->isFunctionProtoType()); |
| New->setImplicit(); |
| New->addAttr(BuiltinAttr::CreateImplicit(Context, ID)); |
| |
| // Create Decl objects for each parameter, adding them to the |
| // FunctionDecl. |
| if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(Type)) { |
| SmallVector<ParmVarDecl *, 16> Params; |
| for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { |
| ParmVarDecl *parm = ParmVarDecl::Create( |
| Context, New, SourceLocation(), SourceLocation(), nullptr, |
| FT->getParamType(i), /*TInfo=*/nullptr, SC_None, nullptr); |
| parm->setScopeInfo(0, i); |
| Params.push_back(parm); |
| } |
| New->setParams(Params); |
| } |
| |
| AddKnownFunctionAttributes(New); |
| return New; |
| } |
| |
| /// LazilyCreateBuiltin - The specified Builtin-ID was first used at |
| /// file scope. lazily create a decl for it. ForRedeclaration is true |
| /// if we're creating this built-in in anticipation of redeclaring the |
| /// built-in. |
| NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, |
| Scope *S, bool ForRedeclaration, |
| SourceLocation Loc) { |
| LookupNecessaryTypesForBuiltin(S, ID); |
| |
| ASTContext::GetBuiltinTypeError Error; |
| QualType R = Context.GetBuiltinType(ID, Error); |
| if (Error) { |
| if (!ForRedeclaration) |
| return nullptr; |
| |
| // If we have a builtin without an associated type we should not emit a |
| // warning when we were not able to find a type for it. |
| if (Error == ASTContext::GE_Missing_type || |
| Context.BuiltinInfo.allowTypeMismatch(ID)) |
| return nullptr; |
| |
| // If we could not find a type for setjmp it is because the jmp_buf type was |
| // not defined prior to the setjmp declaration. |
| if (Error == ASTContext::GE_Missing_setjmp) { |
| Diag(Loc, diag::warn_implicit_decl_no_jmp_buf) |
| << Context.BuiltinInfo.getName(ID); |
| return nullptr; |
| } |
| |
| // Generally, we emit a warning that the declaration requires the |
| // appropriate header. |
| Diag(Loc, diag::warn_implicit_decl_requires_sysheader) |
| << getHeaderName(Context.BuiltinInfo, ID, Error) |
| << Context.BuiltinInfo.getName(ID); |
| return nullptr; |
| } |
| |
| if (!ForRedeclaration && |
| (Context.BuiltinInfo.isPredefinedLibFunction(ID) || |
| Context.BuiltinInfo.isHeaderDependentFunction(ID))) { |
| Diag(Loc, diag::ext_implicit_lib_function_decl) |
| << Context.BuiltinInfo.getName(ID) << R; |
| if (const char *Header = Context.BuiltinInfo.getHeaderName(ID)) |
| Diag(Loc, diag::note_include_header_or_declare) |
| << Header << Context.BuiltinInfo.getName(ID); |
| } |
| |
| if (R.isNull()) |
| return nullptr; |
| |
| FunctionDecl *New = CreateBuiltin(II, R, ID, Loc); |
| RegisterLocallyScopedExternCDecl(New, S); |
| |
| // TUScope is the translation-unit scope to insert this function into. |
| // FIXME: This is hideous. We need to teach PushOnScopeChains to |
| // relate Scopes to DeclContexts, and probably eliminate CurContext |
| // entirely, but we're not there yet. |
| DeclContext *SavedContext = CurContext; |
| CurContext = New->getDeclContext(); |
| PushOnScopeChains(New, TUScope); |
| CurContext = SavedContext; |
| return New; |
| } |
| |
| /// Typedef declarations don't have linkage, but they still denote the same |
| /// entity if their types are the same. |
| /// FIXME: This is notionally doing the same thing as ASTReaderDecl's |
| /// isSameEntity. |
| static void filterNonConflictingPreviousTypedefDecls(Sema &S, |
| TypedefNameDecl *Decl, |
| LookupResult &Previous) { |
| // This is only interesting when modules are enabled. |
| if (!S.getLangOpts().Modules && !S.getLangOpts().ModulesLocalVisibility) |
| return; |
| |
| // Empty sets are uninteresting. |
| if (Previous.empty()) |
| return; |
| |
| LookupResult::Filter Filter = Previous.makeFilter(); |
| while (Filter.hasNext()) { |
| NamedDecl *Old = Filter.next(); |
| |
| // Non-hidden declarations are never ignored. |
| if (S.isVisible(Old)) |
| continue; |
| |
| // Declarations of the same entity are not ignored, even if they have |
| // different linkages. |
| if (auto *OldTD = dyn_cast<TypedefNameDecl>(Old)) { |
| if (S.Context.hasSameType(OldTD->getUnderlyingType(), |
| Decl->getUnderlyingType())) |
| continue; |
| |
| // If both declarations give a tag declaration a typedef name for linkage |
| // purposes, then they declare the same entity. |
| if (OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true) && |
| Decl->getAnonDeclWithTypedefName()) |
| continue; |
| } |
| |
| Filter.erase(); |
| } |
| |
| Filter.done(); |
| } |
| |
| bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { |
| QualType OldType; |
| if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old)) |
| OldType = OldTypedef->getUnderlyingType(); |
| else |
| OldType = Context.getTypeDeclType(Old); |
| QualType NewType = New->getUnderlyingType(); |
| |
| if (NewType->isVariablyModifiedType()) { |
| // Must not redefine a typedef with a variably-modified type. |
| int Kind = isa<TypeAliasDecl>(Old) ? 1 : 0; |
| Diag(New->getLocation(), diag::err_redefinition_variably_modified_typedef) |
| << Kind << NewType; |
| if (Old->getLocation().isValid()) |
| notePreviousDefinition(Old, New->getLocation()); |
| New->setInvalidDecl(); |
| return true; |
| } |
| |
| if (OldType != NewType && |
| !OldType->isDependentType() && |
| !NewType->isDependentType() && |
| !Context.hasSameType(OldType, NewType)) { |
| int Kind = isa<TypeAliasDecl>(Old) ? 1 : 0; |
| Diag(New->getLocation(), diag::err_redefinition_different_typedef) |
| << Kind << NewType << OldType; |
| if (Old->getLocation().isValid()) |
| notePreviousDefinition(Old, New->getLocation()); |
| New->setInvalidDecl(); |
| return true; |
| } |
| return false; |
| } |
| |
| /// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the |
| /// same name and scope as a previous declaration 'Old'. Figure out |
| /// how to resolve this situation, merging decls or emitting |
| /// diagnostics as appropriate. If there was an error, set New to be invalid. |
| /// |
| void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, |
| LookupResult &OldDecls) { |
| // If the new decl is known invalid already, don't bother doing any |
| // merging checks. |
| if (New->isInvalidDecl()) return; |
| |
| // Allow multiple definitions for ObjC built-in typedefs. |
| // FIXME: Verify the underlying types are equivalent! |
| if (getLangOpts().ObjC) { |
| const IdentifierInfo *TypeID = New->getIdentifier(); |
| switch (TypeID->getLength()) { |
| default: break; |
| case 2: |
| { |
| if (!TypeID->isStr("id")) |
| break; |
| QualType T = New->getUnderlyingType(); |
| if (!T->isPointerType()) |
| break; |
| if (!T->isVoidPointerType()) { |
| QualType PT = T->castAs<PointerType>()->getPointeeType(); |
| if (!PT->isStructureType()) |
| break; |
| } |
| Context.setObjCIdRedefinitionType(T); |
| // Install the built-in type for 'id', ignoring the current definition. |
| New->setTypeForDecl(Context.getObjCIdType().getTypePtr()); |
| return; |
| } |
| case 5: |
| if (!TypeID->isStr("Class")) |
| break; |
| Context.setObjCClassRedefinitionType(New->getUnderlyingType()); |
| // Install the built-in type for 'Class', ignoring the current definition. |
| New->setTypeForDecl(Context.getObjCClassType().getTypePtr()); |
| return; |
| case 3: |
| if (!TypeID->isStr("SEL")) |
| break; |
| Context.setObjCSelRedefinitionType(New->getUnderlyingType()); |
| // Install the built-in type for 'SEL', ignoring the current definition. |
| New->setTypeForDecl(Context.getObjCSelType().getTypePtr()); |
| return; |
| } |
| // Fall through - the typedef name was not a builtin type. |
| } |
| |
| // Verify the old decl was also a type. |
| TypeDecl *Old = OldDecls.getAsSingle<TypeDecl>(); |
| if (!Old) { |
| Diag(New->getLocation(), diag::err_redefinition_different_kind) |
| << New->getDeclName(); |
| |
| NamedDecl *OldD = OldDecls.getRepresentativeDecl(); |
| if (OldD->getLocation().isValid()) |
| notePreviousDefinition(OldD, New->getLocation()); |
| |
| return New->setInvalidDecl(); |
| } |
| |
| // If the old declaration is invalid, just give up here. |
| if (Old->isInvalidDecl()) |
| return New->setInvalidDecl(); |
| |
| if (auto *OldTD = dyn_cast<TypedefNameDecl>(Old)) { |
| auto *OldTag = OldTD->getAnonDeclWithTypedefName(/*AnyRedecl*/true); |
| auto *NewTag = New->getAnonDeclWithTypedefName(); |
| NamedDecl *Hidden = nullptr; |
| if (OldTag && NewTag && |
| OldTag->getCanonicalDecl() != NewTag->getCanonicalDecl() && |
| !hasVisibleDefinition(OldTag, &Hidden)) { |
| // There is a definition of this tag, but it is not visible. Use it |
| // instead of our tag. |
| New->setTypeForDecl(OldTD->getTypeForDecl()); |
| if (OldTD->isModed()) |
| New->setModedTypeSourceInfo(OldTD->getTypeSourceInfo(), |
| OldTD->getUnderlyingType()); |
| else |
| New->setTypeSourceInfo(OldTD->getTypeSourceInfo()); |
| |
| // Make the old tag definition visible. |
| makeMergedDefinitionVisible(Hidden); |
| |
| // If this was an unscoped enumeration, yank all of its enumerators |
| // out of the scope. |
| if (isa<EnumDecl>(NewTag)) { |
| Scope *EnumScope = getNonFieldDeclScope(S); |
| for (auto *D : NewTag->decls()) { |
| auto *ED = cast<EnumConstantDecl>(D); |
| assert(EnumScope->isDeclScope(ED)); |
| EnumScope->RemoveDecl(ED); |
| IdResolver.RemoveDecl(ED); |
| ED->getLexicalDeclContext()->removeDecl(ED); |
| } |
| } |
| } |
| } |
| |
| // If the typedef types are not identical, reject them in all languages and |
| // with any extensions enabled. |
| if (isIncompatibleTypedef(Old, New)) |
| return; |
| |
| // The types match. Link up the redeclaration chain and merge attributes if |
| // the old declaration was a typedef. |
| if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old)) { |
| New->setPreviousDecl(Typedef); |
| mergeDeclAttributes(New, Old); |
| } |
| |
| if (getLangOpts().MicrosoftExt) |
| return; |
| |
| if (getLangOpts().CPlusPlus) { |
| // C++ [dcl.typedef]p2: |
| // In a given non-class scope, a typedef specifier can be used to |
| // redefine the name of any type declared in that scope to refer |
| // to the type to which it already refers. |
| if (!isa<CXXRecordDecl>(CurContext)) |
| return; |
| |
| // C++0x [dcl.typedef]p4: |
| // In a given class scope, a typedef specifier can be used to redefine |
| // any class-name declared in that scope that is not also a typedef-name |
| // to refer to the type to which it already refers. |
| // |
| // This wording came in via DR424, which was a correction to the |
| // wording in DR56, which accidentally banned code like: |
| // |
| // struct S { |
| // typedef struct A { } A; |
| // }; |
| // |
| // in the C++03 standard. We implement the C++0x semantics, which |
| // allow the above but disallow |
| // |
| // struct S { |
| // typedef int I; |
| // typedef int I; |
| // }; |
| // |
| // since that was the intent of DR56. |
| if (!isa<TypedefNameDecl>(Old)) |
| return; |
| |
| Diag(New->getLocation(), diag::err_redefinition) |
| << New->getDeclName(); |
| notePreviousDefinition(Old, New->getLocation()); |
| return New->setInvalidDecl(); |
| } |
| |
| // Modules always permit redefinition of typedefs, as does C11. |
| if (getLangOpts().Modules || getLangOpts().C11) |
| return; |
| |
| // If we have a redefinition of a typedef in C, emit a warning. This warning |
| // is normally mapped to an error, but can be controlled with |
| // -Wtypedef-redefinition. If either the original or the redefinition is |
| // in a system header, don't emit this for compatibility with GCC. |
| if (getDiagnostics().getSuppressSystemWarnings() && |
| // Some standard types are defined implicitly in Clang (e.g. OpenCL). |
| (Old->isImplicit() || |
| Context.getSourceManager().isInSystemHeader(Old->getLocation()) || |
| Context.getSourceManager().isInSystemHeader(New->getLocation()))) |
| return; |
| |
| Diag(New->getLocation(), diag::ext_redefinition_of_typedef) |
| << New->getDeclName(); |
| notePreviousDefinition(Old, New->getLocation()); |
| } |
| |
| /// DeclhasAttr - returns true if decl Declaration already has the target |
| /// attribute. |
| static bool DeclHasAttr(const Decl *D, const Attr *A) { |
| const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A); |
| const AnnotateAttr *Ann = dyn_cast<AnnotateAttr>(A); |
| for (const auto *i : D->attrs()) |
| if (i->getKind() == A->getKind()) { |
| if (Ann) { |
| if (Ann->getAnnotation() == cast<AnnotateAttr>(i)->getAnnotation()) |
| return true; |
| continue; |
| } |
| // FIXME: Don't hardcode this check |
| if (OA && isa<OwnershipAttr>(i)) |
| return OA->getOwnKind() == cast<OwnershipAttr>(i)->getOwnKind(); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| static bool isAttributeTargetADefinition(Decl *D) { |
| if (VarDecl *VD = dyn_cast<VarDecl>(D)) |
| return VD->isThisDeclarationADefinition(); |
| if (TagDecl *TD = dyn_cast<TagDecl>(D)) |
| return TD->isCompleteDefinition() || TD->isBeingDefined(); |
| return true; |
| } |
| |
| /// Merge alignment attributes from \p Old to \p New, taking into account the |
| /// special semantics of C11's _Alignas specifier and C++11's alignas attribute. |
| /// |
| /// \return \c true if any attributes were added to \p New. |
| static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) { |
| // Look for alignas attributes on Old, and pick out whichever attribute |
| // specifies the strictest alignment requirement. |
| AlignedAttr *OldAlignasAttr = nullptr; |
| AlignedAttr *OldStrictestAlignAttr = nullptr; |
| unsigned OldAlign = 0; |
| for (auto *I : Old->specific_attrs<AlignedAttr>()) { |
| // FIXME: We have no way of representing inherited dependent alignments |
| // in a case like: |
| // template<int A, int B> struct alignas(A) X; |
| // template<int A, int B> struct alignas(B) X {}; |
| // For now, we just ignore any alignas attributes which are not on the |
| // definition in such a case. |
| if (I->isAlignmentDependent()) |
| return false; |
| |
| if (I->isAlignas()) |
| OldAlignasAttr = I; |
| |
| unsigned Align = I->getAlignment(S.Context); |
| if (Align > OldAlign) { |
| OldAlign = Align; |
| OldStrictestAlignAttr = I; |
| } |
| } |
| |
| // Look for alignas attributes on New. |
| AlignedAttr *NewAlignasAttr = nullptr; |
| unsigned NewAlign = 0; |
| for (auto *I : New->specific_attrs<AlignedAttr>()) { |
| if (I->isAlignmentDependent()) |
| return false; |
| |
| if (I->isAlignas()) |
| NewAlignasAttr = I; |
| |
| unsigned Align = I->getAlignment(S.Context); |
| if (Align > NewAlign) |
| NewAlign = Align; |
| } |
| |
| if (OldAlignasAttr && NewAlignasAttr && OldAlign != NewAlign) { |
| // Both declarations have 'alignas' attributes. We require them to match. |
| // C++11 [dcl.align]p6 and C11 6.7.5/7 both come close to saying this, but |
| // fall short. (If two declarations both have alignas, they must both match |
| // every definition, and so must match each other if there is a definition.) |
| |
| // If either declaration only contains 'alignas(0)' specifiers, then it |
| // specifies the natural alignment for the type. |
| if (OldAlign == 0 || NewAlign == 0) { |
| QualType Ty; |
| if (ValueDecl *VD = dyn_cast<ValueDecl>(New)) |
| Ty = VD->getType(); |
| else |
| Ty = S.Context.getTagDeclType(cast<TagDecl>(New)); |
| |
| if (OldAlign == 0) |
| OldAlign = S.Context.getTypeAlign(Ty); |
| if (NewAlign == 0) |
| NewAlign = S.Context.getTypeAlign(Ty); |
| } |
| |
| if (OldAlign != NewAlign) { |
| S.Diag(NewAlignasAttr->getLocation(), diag::err_alignas_mismatch) |
| << (unsigned)S.Context.toCharUnitsFromBits(OldAlign).getQuantity() |
| << (unsigned)S.Context.toCharUnitsFromBits(NewAlign).getQuantity(); |
| S.Diag(OldAlignasAttr->getLocation(), diag::note_previous_declaration); |
| } |
| } |
| |
| if (OldAlignasAttr && !NewAlignasAttr && isAttributeTargetADefinition(New)) { |
| // C++11 [dcl.align]p6: |
| // if any declaration of an entity has an alignment-specifier, |
| // every defining declaration of that entity shall specify an |
| // equivalent alignment. |
| // C11 6.7.5/7: |
| // If the definition of an object does not have an alignment |
| // specifier, any other declaration of that object shall also |
| // have no alignment specifier. |
| S.Diag(New->getLocation(), diag::err_alignas_missing_on_definition) |
| << OldAlignasAttr; |
| S.Diag(OldAlignasAttr->getLocation(), diag::note_alignas_on_declaration) |
| << OldAlignasAttr; |
| } |
| |
| bool AnyAdded = false; |
| |
| // Ensure we have an attribute representing the strictest alignment. |
| if (OldAlign > NewAlign) { |
| AlignedAttr *Clone = OldStrictestAlignAttr->clone(S.Context); |
| Clone->setInherited(true); |
| New->addAttr(Clone); |
| AnyAdded = true; |
| } |
| |
| // Ensure we have an alignas attribute if the old declaration had one. |
| if (OldAlignasAttr && !NewAlignasAttr && |
| !(AnyAdded && OldStrictestAlignAttr->isAlignas())) { |
| AlignedAttr *Clone = OldAlignasAttr->clone(S.Context); |
| Clone->setInherited(true); |
| New->addAttr(Clone); |
| AnyAdded = true; |
| } |
| |
| return AnyAdded; |
| } |
| |
| #define WANT_DECL_MERGE_LOGIC |
| #include "clang/Sema/AttrParsedAttrImpl.inc" |
| #undef WANT_DECL_MERGE_LOGIC |
| |
| static bool mergeDeclAttribute(Sema &S, NamedDecl *D, |
| const InheritableAttr *Attr, |
| Sema::AvailabilityMergeKind AMK) { |
| // Diagnose any mutual exclusions between the attribute that we want to add |
| // and attributes that already exist on the declaration. |
| if (!DiagnoseMutualExclusions(S, D, Attr)) |
| return false; |
| |
| // This function copies an attribute Attr from a previous declaration to the |
| // new declaration D if the new declaration doesn't itself have that attribute |
| // yet or if that attribute allows duplicates. |
| // If you're adding a new attribute that requires logic different from |
| // "use explicit attribute on decl if present, else use attribute from |
| // previous decl", for example if the attribute needs to be consistent |
| // between redeclarations, you need to call a custom merge function here. |
| InheritableAttr *NewAttr = nullptr; |
| if (const auto *AA = dyn_cast<AvailabilityAttr>(Attr)) |
| NewAttr = S.mergeAvailabilityAttr( |
| D, *AA, AA->getPlatform(), AA->isImplicit(), AA->getIntroduced(), |
| AA->getDeprecated(), AA->getObsoleted(), AA->getUnavailable(), |
| AA->getMessage(), AA->getStrict(), AA->getReplacement(), AMK, |
| AA->getPriority()); |
| else if (const auto *VA = dyn_cast<VisibilityAttr>(Attr)) |
| NewAttr = S.mergeVisibilityAttr(D, *VA, VA->getVisibility()); |
| else if (const auto *VA = dyn_cast<TypeVisibilityAttr>(Attr)) |
| NewAttr = S.mergeTypeVisibilityAttr(D, *VA, VA->getVisibility()); |
| else if (const auto *ImportA = dyn_cast<DLLImportAttr>(Attr)) |
| NewAttr = S.mergeDLLImportAttr(D, *ImportA); |
| else if (const auto *ExportA = dyn_cast<DLLExportAttr>(Attr)) |
| NewAttr = S.mergeDLLExportAttr(D, *ExportA); |
| else if (const auto *EA = dyn_cast<ErrorAttr>(Attr)) |
| NewAttr = S.mergeErrorAttr(D, *EA, EA->getUserDiagnostic()); |
| else if (const auto *FA = dyn_cast<FormatAttr>(Attr)) |
| NewAttr = S.mergeFormatAttr(D, *FA, FA->getType(), FA->getFormatIdx(), |
| FA->getFirstArg()); |
| else if (const auto *SA = dyn_cast<SectionAttr>(Attr)) |
| NewAttr = S.mergeSectionAttr(D, *SA, SA->getName()); |
| else if (const auto *CSA = dyn_cast<CodeSegAttr>(Attr)) |
| NewAttr = S.mergeCodeSegAttr(D, *CSA, CSA->getName()); |
| else if (const auto *IA = dyn_cast<MSInheritanceAttr>(Attr)) |
| NewAttr = S.mergeMSInheritanceAttr(D, *IA, IA->getBestCase(), |
| IA->getInheritanceModel()); |
| else if (const auto *AA = dyn_cast<AlwaysInlineAttr>(Attr)) |
| NewAttr = S.mergeAlwaysInlineAttr(D, *AA, |
| &S.Context.Idents.get(AA->getSpelling())); |
| else if (S.getLangOpts().CUDA && isa<FunctionDecl>(D) && |
| (isa<CUDAHostAttr>(Attr) || isa<CUDADeviceAttr>(Attr) || |
| isa<CUDAGlobalAttr>(Attr))) { |
| // CUDA target attributes are part of function signature for |
| // overloading purposes and must not be merged. |
| return false; |
| } else if (const auto *MA = dyn_cast<MinSizeAttr>(Attr)) |
| NewAttr = S.mergeMinSizeAttr(D, *MA); |
| else if (const auto *SNA = dyn_cast<SwiftNameAttr>(Attr)) |
| NewAttr = S.mergeSwiftNameAttr(D, *SNA, SNA->getName()); |
| else if (const auto *OA = dyn_cast<OptimizeNoneAttr>(Attr)) |
| NewAttr = S.mergeOptimizeNoneAttr(D, *OA); |
| else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr)) |
| NewAttr = S.mergeInternalLinkageAttr(D, *InternalLinkageA); |
| else if (isa<AlignedAttr>(Attr)) |
| // AlignedAttrs are handled separately, because we need to handle all |
| // such attributes on a declaration at the same time. |
| NewAttr = nullptr; |
| else if ((isa<DeprecatedAttr>(Attr) || isa<UnavailableAttr>(Attr)) && |
| (AMK == Sema::AMK_Override || |
| AMK == Sema::AMK_ProtocolImplementation || |
| AMK == Sema::AMK_OptionalProtocolImplementation)) |
| NewAttr = nullptr; |
| else if (const auto *UA = dyn_cast<UuidAttr>(Attr)) |
| NewAttr = S.mergeUuidAttr(D, *UA, UA->getGuid(), UA->getGuidDecl()); |
| else if (const auto *IMA = dyn_cast<WebAssemblyImportModuleAttr>(Attr)) |
| NewAttr = S.mergeImportModuleAttr(D, *IMA); |
| else if (const auto *INA = dyn_cast<WebAssemblyImportNameAttr>(Attr)) |
| NewAttr = S.mergeImportNameAttr(D, *INA); |
| else if (const auto *TCBA = dyn_cast<EnforceTCBAttr>(Attr)) |
| NewAttr = S.mergeEnforceTCBAttr(D, *TCBA); |
| else if (const auto *TCBLA = dyn_cast<EnforceTCBLeafAttr>(Attr)) |
| NewAttr = S.mergeEnforceTCBLeafAttr(D, *TCBLA); |
| else if (const auto *BTFA = dyn_cast<BTFDeclTagAttr>(Attr)) |
| NewAttr = S.mergeBTFDeclTagAttr(D, *BTFA); |
| else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr)) |
| NewAttr = cast<InheritableAttr>(Attr->clone(S.Context)); |
| |
| if (NewAttr) { |
| NewAttr->setInherited(true); |
| D->addAttr(NewAttr); |
| if (isa<MSInheritanceAttr>(NewAttr)) |
| S.Consumer.AssignInheritanceModel(cast<CXXRecordDecl>(D)); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| static const NamedDecl *getDefinition(const Decl *D) { |
| if (const TagDecl *TD = dyn_cast<TagDecl>(D)) |
| return TD->getDefinition(); |
| if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { |
| const VarDecl *Def = VD->getDefinition(); |
| if (Def) |
| return Def; |
| return VD->getActingDefinition(); |
| } |
| if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { |
| const FunctionDecl *Def = nullptr; |
| if (FD->isDefined(Def, true)) |
| return Def; |
|