| //===--- Sema.h - Semantic Analysis & AST Building --------------*- C++ -*-===// |
| // |
| // 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 defines the Sema class, which performs semantic analysis and |
| // builds ASTs. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_SEMA_SEMA_H |
| #define LLVM_CLANG_SEMA_SEMA_H |
| |
| #include "clang/AST/Attr.h" |
| #include "clang/AST/Availability.h" |
| #include "clang/AST/ComparisonCategories.h" |
| #include "clang/AST/DeclTemplate.h" |
| #include "clang/AST/DeclarationName.h" |
| #include "clang/AST/Expr.h" |
| #include "clang/AST/ExprCXX.h" |
| #include "clang/AST/ExprObjC.h" |
| #include "clang/AST/ExternalASTSource.h" |
| #include "clang/AST/LocInfoType.h" |
| #include "clang/AST/MangleNumberingContext.h" |
| #include "clang/AST/NSAPI.h" |
| #include "clang/AST/PrettyPrinter.h" |
| #include "clang/AST/StmtCXX.h" |
| #include "clang/AST/TypeLoc.h" |
| #include "clang/AST/TypeOrdering.h" |
| #include "clang/Basic/ExpressionTraits.h" |
| #include "clang/Basic/Module.h" |
| #include "clang/Basic/OpenMPKinds.h" |
| #include "clang/Basic/PragmaKinds.h" |
| #include "clang/Basic/Specifiers.h" |
| #include "clang/Basic/TemplateKinds.h" |
| #include "clang/Basic/TypeTraits.h" |
| #include "clang/Sema/AnalysisBasedWarnings.h" |
| #include "clang/Sema/CleanupInfo.h" |
| #include "clang/Sema/DeclSpec.h" |
| #include "clang/Sema/ExternalSemaSource.h" |
| #include "clang/Sema/IdentifierResolver.h" |
| #include "clang/Sema/ObjCMethodList.h" |
| #include "clang/Sema/Ownership.h" |
| #include "clang/Sema/Scope.h" |
| #include "clang/Sema/TypoCorrection.h" |
| #include "clang/Sema/Weak.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/Optional.h" |
| #include "llvm/ADT/SetVector.h" |
| #include "llvm/ADT/SmallBitVector.h" |
| #include "llvm/ADT/SmallPtrSet.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/ADT/TinyPtrVector.h" |
| #include <deque> |
| #include <memory> |
| #include <string> |
| #include <tuple> |
| #include <vector> |
| |
| namespace llvm { |
| class APSInt; |
| template <typename ValueT> struct DenseMapInfo; |
| template <typename ValueT, typename ValueInfoT> class DenseSet; |
| class SmallBitVector; |
| struct InlineAsmIdentifierInfo; |
| } |
| |
| namespace clang { |
| class ADLResult; |
| class ASTConsumer; |
| class ASTContext; |
| class ASTMutationListener; |
| class ASTReader; |
| class ASTWriter; |
| class ArrayType; |
| class ParsedAttr; |
| class BindingDecl; |
| class BlockDecl; |
| class CapturedDecl; |
| class CXXBasePath; |
| class CXXBasePaths; |
| class CXXBindTemporaryExpr; |
| typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath; |
| class CXXConstructorDecl; |
| class CXXConversionDecl; |
| class CXXDeleteExpr; |
| class CXXDestructorDecl; |
| class CXXFieldCollector; |
| class CXXMemberCallExpr; |
| class CXXMethodDecl; |
| class CXXScopeSpec; |
| class CXXTemporary; |
| class CXXTryStmt; |
| class CallExpr; |
| class ClassTemplateDecl; |
| class ClassTemplatePartialSpecializationDecl; |
| class ClassTemplateSpecializationDecl; |
| class VarTemplatePartialSpecializationDecl; |
| class CodeCompleteConsumer; |
| class CodeCompletionAllocator; |
| class CodeCompletionTUInfo; |
| class CodeCompletionResult; |
| class CoroutineBodyStmt; |
| class Decl; |
| class DeclAccessPair; |
| class DeclContext; |
| class DeclRefExpr; |
| class DeclaratorDecl; |
| class DeducedTemplateArgument; |
| class DependentDiagnostic; |
| class DesignatedInitExpr; |
| class Designation; |
| class EnableIfAttr; |
| class EnumConstantDecl; |
| class Expr; |
| class ExtVectorType; |
| class FormatAttr; |
| class FriendDecl; |
| class FunctionDecl; |
| class FunctionProtoType; |
| class FunctionTemplateDecl; |
| class ImplicitConversionSequence; |
| typedef MutableArrayRef<ImplicitConversionSequence> ConversionSequenceList; |
| class InitListExpr; |
| class InitializationKind; |
| class InitializationSequence; |
| class InitializedEntity; |
| class IntegerLiteral; |
| class LabelStmt; |
| class LambdaExpr; |
| class LangOptions; |
| class LocalInstantiationScope; |
| class LookupResult; |
| class MacroInfo; |
| typedef ArrayRef<std::pair<IdentifierInfo *, SourceLocation>> ModuleIdPath; |
| class ModuleLoader; |
| class MultiLevelTemplateArgumentList; |
| class NamedDecl; |
| class ObjCCategoryDecl; |
| class ObjCCategoryImplDecl; |
| class ObjCCompatibleAliasDecl; |
| class ObjCContainerDecl; |
| class ObjCImplDecl; |
| class ObjCImplementationDecl; |
| class ObjCInterfaceDecl; |
| class ObjCIvarDecl; |
| template <class T> class ObjCList; |
| class ObjCMessageExpr; |
| class ObjCMethodDecl; |
| class ObjCPropertyDecl; |
| class ObjCProtocolDecl; |
| class OMPThreadPrivateDecl; |
| class OMPRequiresDecl; |
| class OMPDeclareReductionDecl; |
| class OMPDeclareSimdDecl; |
| class OMPClause; |
| struct OMPVarListLocTy; |
| struct OverloadCandidate; |
| enum class OverloadCandidateParamOrder : char; |
| enum OverloadCandidateRewriteKind : unsigned; |
| class OverloadCandidateSet; |
| class OverloadExpr; |
| class ParenListExpr; |
| class ParmVarDecl; |
| class Preprocessor; |
| class PseudoDestructorTypeStorage; |
| class PseudoObjectExpr; |
| class QualType; |
| class StandardConversionSequence; |
| class Stmt; |
| class StringLiteral; |
| class SwitchStmt; |
| class TemplateArgument; |
| class TemplateArgumentList; |
| class TemplateArgumentLoc; |
| class TemplateDecl; |
| class TemplateInstantiationCallback; |
| class TemplateParameterList; |
| class TemplatePartialOrderingContext; |
| class TemplateTemplateParmDecl; |
| class Token; |
| class TypeAliasDecl; |
| class TypedefDecl; |
| class TypedefNameDecl; |
| class TypeLoc; |
| class TypoCorrectionConsumer; |
| class UnqualifiedId; |
| class UnresolvedLookupExpr; |
| class UnresolvedMemberExpr; |
| class UnresolvedSetImpl; |
| class UnresolvedSetIterator; |
| class UsingDecl; |
| class UsingShadowDecl; |
| class ValueDecl; |
| class VarDecl; |
| class VarTemplateSpecializationDecl; |
| class VisibilityAttr; |
| class VisibleDeclConsumer; |
| class IndirectFieldDecl; |
| struct DeductionFailureInfo; |
| class TemplateSpecCandidateSet; |
| |
| namespace sema { |
| class AccessedEntity; |
| class BlockScopeInfo; |
| class Capture; |
| class CapturedRegionScopeInfo; |
| class CapturingScopeInfo; |
| class CompoundScopeInfo; |
| class DelayedDiagnostic; |
| class DelayedDiagnosticPool; |
| class FunctionScopeInfo; |
| class LambdaScopeInfo; |
| class PossiblyUnreachableDiag; |
| class SemaPPCallbacks; |
| class TemplateDeductionInfo; |
| } |
| |
| namespace threadSafety { |
| class BeforeSet; |
| void threadSafetyCleanup(BeforeSet* Cache); |
| } |
| |
| // FIXME: No way to easily map from TemplateTypeParmTypes to |
| // TemplateTypeParmDecls, so we have this horrible PointerUnion. |
| typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, NamedDecl*>, |
| SourceLocation> UnexpandedParameterPack; |
| |
| /// Describes whether we've seen any nullability information for the given |
| /// file. |
| struct FileNullability { |
| /// The first pointer declarator (of any pointer kind) in the file that does |
| /// not have a corresponding nullability annotation. |
| SourceLocation PointerLoc; |
| |
| /// The end location for the first pointer declarator in the file. Used for |
| /// placing fix-its. |
| SourceLocation PointerEndLoc; |
| |
| /// Which kind of pointer declarator we saw. |
| uint8_t PointerKind; |
| |
| /// Whether we saw any type nullability annotations in the given file. |
| bool SawTypeNullability = false; |
| }; |
| |
| /// A mapping from file IDs to a record of whether we've seen nullability |
| /// information in that file. |
| class FileNullabilityMap { |
| /// A mapping from file IDs to the nullability information for each file ID. |
| llvm::DenseMap<FileID, FileNullability> Map; |
| |
| /// A single-element cache based on the file ID. |
| struct { |
| FileID File; |
| FileNullability Nullability; |
| } Cache; |
| |
| public: |
| FileNullability &operator[](FileID file) { |
| // Check the single-element cache. |
| if (file == Cache.File) |
| return Cache.Nullability; |
| |
| // It's not in the single-element cache; flush the cache if we have one. |
| if (!Cache.File.isInvalid()) { |
| Map[Cache.File] = Cache.Nullability; |
| } |
| |
| // Pull this entry into the cache. |
| Cache.File = file; |
| Cache.Nullability = Map[file]; |
| return Cache.Nullability; |
| } |
| }; |
| |
| /// Keeps track of expected type during expression parsing. The type is tied to |
| /// a particular token, all functions that update or consume the type take a |
| /// start location of the token they are looking at as a parameter. This allows |
| /// to avoid updating the type on hot paths in the parser. |
| class PreferredTypeBuilder { |
| public: |
| PreferredTypeBuilder() = default; |
| explicit PreferredTypeBuilder(QualType Type) : Type(Type) {} |
| |
| void enterCondition(Sema &S, SourceLocation Tok); |
| void enterReturn(Sema &S, SourceLocation Tok); |
| void enterVariableInit(SourceLocation Tok, Decl *D); |
| /// Computing a type for the function argument may require running |
| /// overloading, so we postpone its computation until it is actually needed. |
| /// |
| /// Clients should be very careful when using this funciton, as it stores a |
| /// function_ref, clients should make sure all calls to get() with the same |
| /// location happen while function_ref is alive. |
| void enterFunctionArgument(SourceLocation Tok, |
| llvm::function_ref<QualType()> ComputeType); |
| |
| void enterParenExpr(SourceLocation Tok, SourceLocation LParLoc); |
| void enterUnary(Sema &S, SourceLocation Tok, tok::TokenKind OpKind, |
| SourceLocation OpLoc); |
| void enterBinary(Sema &S, SourceLocation Tok, Expr *LHS, tok::TokenKind Op); |
| void enterMemAccess(Sema &S, SourceLocation Tok, Expr *Base); |
| void enterSubscript(Sema &S, SourceLocation Tok, Expr *LHS); |
| /// Handles all type casts, including C-style cast, C++ casts, etc. |
| void enterTypeCast(SourceLocation Tok, QualType CastType); |
| |
| QualType get(SourceLocation Tok) const { |
| if (Tok != ExpectedLoc) |
| return QualType(); |
| if (!Type.isNull()) |
| return Type; |
| if (ComputeType) |
| return ComputeType(); |
| return QualType(); |
| } |
| |
| private: |
| /// Start position of a token for which we store expected type. |
| SourceLocation ExpectedLoc; |
| /// Expected type for a token starting at ExpectedLoc. |
| QualType Type; |
| /// A function to compute expected type at ExpectedLoc. It is only considered |
| /// if Type is null. |
| llvm::function_ref<QualType()> ComputeType; |
| }; |
| |
| /// Sema - This implements semantic analysis and AST building for C. |
| class Sema { |
| Sema(const Sema &) = delete; |
| void operator=(const Sema &) = delete; |
| |
| ///Source of additional semantic information. |
| ExternalSemaSource *ExternalSource; |
| |
| ///Whether Sema has generated a multiplexer and has to delete it. |
| bool isMultiplexExternalSource; |
| |
| static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD); |
| |
| bool isVisibleSlow(const NamedDecl *D); |
| |
| /// Determine whether two declarations should be linked together, given that |
| /// the old declaration might not be visible and the new declaration might |
| /// not have external linkage. |
| bool shouldLinkPossiblyHiddenDecl(const NamedDecl *Old, |
| const NamedDecl *New) { |
| if (isVisible(Old)) |
| return true; |
| // See comment in below overload for why it's safe to compute the linkage |
| // of the new declaration here. |
| if (New->isExternallyDeclarable()) { |
| assert(Old->isExternallyDeclarable() && |
| "should not have found a non-externally-declarable previous decl"); |
| return true; |
| } |
| return false; |
| } |
| bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New); |
| |
| void setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem, |
| QualType ResultTy, |
| ArrayRef<QualType> Args); |
| |
| public: |
| typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy; |
| typedef OpaquePtr<TemplateName> TemplateTy; |
| typedef OpaquePtr<QualType> TypeTy; |
| |
| OpenCLOptions OpenCLFeatures; |
| FPOptions FPFeatures; |
| |
| const LangOptions &LangOpts; |
| Preprocessor &PP; |
| ASTContext &Context; |
| ASTConsumer &Consumer; |
| DiagnosticsEngine &Diags; |
| SourceManager &SourceMgr; |
| |
| /// Flag indicating whether or not to collect detailed statistics. |
| bool CollectStats; |
| |
| /// Code-completion consumer. |
| CodeCompleteConsumer *CodeCompleter; |
| |
| /// CurContext - This is the current declaration context of parsing. |
| DeclContext *CurContext; |
| |
| /// Generally null except when we temporarily switch decl contexts, |
| /// like in \see ActOnObjCTemporaryExitContainerContext. |
| DeclContext *OriginalLexicalContext; |
| |
| /// VAListTagName - The declaration name corresponding to __va_list_tag. |
| /// This is used as part of a hack to omit that class from ADL results. |
| DeclarationName VAListTagName; |
| |
| bool MSStructPragmaOn; // True when \#pragma ms_struct on |
| |
| /// Controls member pointer representation format under the MS ABI. |
| LangOptions::PragmaMSPointersToMembersKind |
| MSPointerToMemberRepresentationMethod; |
| |
| /// Stack of active SEH __finally scopes. Can be empty. |
| SmallVector<Scope*, 2> CurrentSEHFinally; |
| |
| /// Source location for newly created implicit MSInheritanceAttrs |
| SourceLocation ImplicitMSInheritanceAttrLoc; |
| |
| /// Holds TypoExprs that are created from `createDelayedTypo`. This is used by |
| /// `TransformTypos` in order to keep track of any TypoExprs that are created |
| /// recursively during typo correction and wipe them away if the correction |
| /// fails. |
| llvm::SmallVector<TypoExpr *, 2> TypoExprs; |
| |
| /// pragma clang section kind |
| enum PragmaClangSectionKind { |
| PCSK_Invalid = 0, |
| PCSK_BSS = 1, |
| PCSK_Data = 2, |
| PCSK_Rodata = 3, |
| PCSK_Text = 4, |
| PCSK_Relro = 5 |
| }; |
| |
| enum PragmaClangSectionAction { |
| PCSA_Set = 0, |
| PCSA_Clear = 1 |
| }; |
| |
| struct PragmaClangSection { |
| std::string SectionName; |
| bool Valid = false; |
| SourceLocation PragmaLocation; |
| |
| void Act(SourceLocation PragmaLocation, |
| PragmaClangSectionAction Action, |
| StringLiteral* Name); |
| }; |
| |
| PragmaClangSection PragmaClangBSSSection; |
| PragmaClangSection PragmaClangDataSection; |
| PragmaClangSection PragmaClangRodataSection; |
| PragmaClangSection PragmaClangRelroSection; |
| PragmaClangSection PragmaClangTextSection; |
| |
| enum PragmaMsStackAction { |
| PSK_Reset = 0x0, // #pragma () |
| PSK_Set = 0x1, // #pragma (value) |
| PSK_Push = 0x2, // #pragma (push[, id]) |
| PSK_Pop = 0x4, // #pragma (pop[, id]) |
| PSK_Show = 0x8, // #pragma (show) -- only for "pack"! |
| PSK_Push_Set = PSK_Push | PSK_Set, // #pragma (push[, id], value) |
| PSK_Pop_Set = PSK_Pop | PSK_Set, // #pragma (pop[, id], value) |
| }; |
| |
| template<typename ValueType> |
| struct PragmaStack { |
| struct Slot { |
| llvm::StringRef StackSlotLabel; |
| ValueType Value; |
| SourceLocation PragmaLocation; |
| SourceLocation PragmaPushLocation; |
| Slot(llvm::StringRef StackSlotLabel, ValueType Value, |
| SourceLocation PragmaLocation, SourceLocation PragmaPushLocation) |
| : StackSlotLabel(StackSlotLabel), Value(Value), |
| PragmaLocation(PragmaLocation), |
| PragmaPushLocation(PragmaPushLocation) {} |
| }; |
| void Act(SourceLocation PragmaLocation, |
| PragmaMsStackAction Action, |
| llvm::StringRef StackSlotLabel, |
| ValueType Value); |
| |
| // MSVC seems to add artificial slots to #pragma stacks on entering a C++ |
| // method body to restore the stacks on exit, so it works like this: |
| // |
| // struct S { |
| // #pragma <name>(push, InternalPragmaSlot, <current_pragma_value>) |
| // void Method {} |
| // #pragma <name>(pop, InternalPragmaSlot) |
| // }; |
| // |
| // It works even with #pragma vtordisp, although MSVC doesn't support |
| // #pragma vtordisp(push [, id], n) |
| // syntax. |
| // |
| // Push / pop a named sentinel slot. |
| void SentinelAction(PragmaMsStackAction Action, StringRef Label) { |
| assert((Action == PSK_Push || Action == PSK_Pop) && |
| "Can only push / pop #pragma stack sentinels!"); |
| Act(CurrentPragmaLocation, Action, Label, CurrentValue); |
| } |
| |
| // Constructors. |
| explicit PragmaStack(const ValueType &Default) |
| : DefaultValue(Default), CurrentValue(Default) {} |
| |
| bool hasValue() const { return CurrentValue != DefaultValue; } |
| |
| SmallVector<Slot, 2> Stack; |
| ValueType DefaultValue; // Value used for PSK_Reset action. |
| ValueType CurrentValue; |
| SourceLocation CurrentPragmaLocation; |
| }; |
| // FIXME: We should serialize / deserialize these if they occur in a PCH (but |
| // we shouldn't do so if they're in a module). |
| |
| /// Whether to insert vtordisps prior to virtual bases in the Microsoft |
| /// C++ ABI. Possible values are 0, 1, and 2, which mean: |
| /// |
| /// 0: Suppress all vtordisps |
| /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial |
| /// structors |
| /// 2: Always insert vtordisps to support RTTI on partially constructed |
| /// objects |
| PragmaStack<MSVtorDispAttr::Mode> VtorDispStack; |
| // #pragma pack. |
| // Sentinel to represent when the stack is set to mac68k alignment. |
| static const unsigned kMac68kAlignmentSentinel = ~0U; |
| PragmaStack<unsigned> PackStack; |
| // The current #pragma pack values and locations at each #include. |
| struct PackIncludeState { |
| unsigned CurrentValue; |
| SourceLocation CurrentPragmaLocation; |
| bool HasNonDefaultValue, ShouldWarnOnInclude; |
| }; |
| SmallVector<PackIncludeState, 8> PackIncludeStack; |
| // Segment #pragmas. |
| PragmaStack<StringLiteral *> DataSegStack; |
| PragmaStack<StringLiteral *> BSSSegStack; |
| PragmaStack<StringLiteral *> ConstSegStack; |
| PragmaStack<StringLiteral *> CodeSegStack; |
| |
| // RAII object to push / pop sentinel slots for all MS #pragma stacks. |
| // Actions should be performed only if we enter / exit a C++ method body. |
| class PragmaStackSentinelRAII { |
| public: |
| PragmaStackSentinelRAII(Sema &S, StringRef SlotLabel, bool ShouldAct); |
| ~PragmaStackSentinelRAII(); |
| |
| private: |
| Sema &S; |
| StringRef SlotLabel; |
| bool ShouldAct; |
| }; |
| |
| /// A mapping that describes the nullability we've seen in each header file. |
| FileNullabilityMap NullabilityMap; |
| |
| /// Last section used with #pragma init_seg. |
| StringLiteral *CurInitSeg; |
| SourceLocation CurInitSegLoc; |
| |
| /// VisContext - Manages the stack for \#pragma GCC visibility. |
| void *VisContext; // Really a "PragmaVisStack*" |
| |
| /// This an attribute introduced by \#pragma clang attribute. |
| struct PragmaAttributeEntry { |
| SourceLocation Loc; |
| ParsedAttr *Attribute; |
| SmallVector<attr::SubjectMatchRule, 4> MatchRules; |
| bool IsUsed; |
| }; |
| |
| /// A push'd group of PragmaAttributeEntries. |
| struct PragmaAttributeGroup { |
| /// The location of the push attribute. |
| SourceLocation Loc; |
| /// The namespace of this push group. |
| const IdentifierInfo *Namespace; |
| SmallVector<PragmaAttributeEntry, 2> Entries; |
| }; |
| |
| SmallVector<PragmaAttributeGroup, 2> PragmaAttributeStack; |
| |
| /// The declaration that is currently receiving an attribute from the |
| /// #pragma attribute stack. |
| const Decl *PragmaAttributeCurrentTargetDecl; |
| |
| /// This represents the last location of a "#pragma clang optimize off" |
| /// directive if such a directive has not been closed by an "on" yet. If |
| /// optimizations are currently "on", this is set to an invalid location. |
| SourceLocation OptimizeOffPragmaLocation; |
| |
| /// Flag indicating if Sema is building a recovery call expression. |
| /// |
| /// This flag is used to avoid building recovery call expressions |
| /// if Sema is already doing so, which would cause infinite recursions. |
| bool IsBuildingRecoveryCallExpr; |
| |
| /// Used to control the generation of ExprWithCleanups. |
| CleanupInfo Cleanup; |
| |
| /// ExprCleanupObjects - This is the stack of objects requiring |
| /// cleanup that are created by the current full expression. The |
| /// element type here is ExprWithCleanups::Object. |
| SmallVector<BlockDecl*, 8> ExprCleanupObjects; |
| |
| /// Store a set of either DeclRefExprs or MemberExprs that contain a reference |
| /// to a variable (constant) that may or may not be odr-used in this Expr, and |
| /// we won't know until all lvalue-to-rvalue and discarded value conversions |
| /// have been applied to all subexpressions of the enclosing full expression. |
| /// This is cleared at the end of each full expression. |
| using MaybeODRUseExprSet = llvm::SmallPtrSet<Expr *, 2>; |
| MaybeODRUseExprSet MaybeODRUseExprs; |
| |
| std::unique_ptr<sema::FunctionScopeInfo> CachedFunctionScope; |
| |
| /// Stack containing information about each of the nested |
| /// function, block, and method scopes that are currently active. |
| SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes; |
| |
| typedef LazyVector<TypedefNameDecl *, ExternalSemaSource, |
| &ExternalSemaSource::ReadExtVectorDecls, 2, 2> |
| ExtVectorDeclsType; |
| |
| /// ExtVectorDecls - This is a list all the extended vector types. This allows |
| /// us to associate a raw vector type with one of the ext_vector type names. |
| /// This is only necessary for issuing pretty diagnostics. |
| ExtVectorDeclsType ExtVectorDecls; |
| |
| /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. |
| std::unique_ptr<CXXFieldCollector> FieldCollector; |
| |
| typedef llvm::SmallSetVector<NamedDecl *, 16> NamedDeclSetType; |
| |
| /// Set containing all declared private fields that are not used. |
| NamedDeclSetType UnusedPrivateFields; |
| |
| /// Set containing all typedefs that are likely unused. |
| llvm::SmallSetVector<const TypedefNameDecl *, 4> |
| UnusedLocalTypedefNameCandidates; |
| |
| /// Delete-expressions to be analyzed at the end of translation unit |
| /// |
| /// This list contains class members, and locations of delete-expressions |
| /// that could not be proven as to whether they mismatch with new-expression |
| /// used in initializer of the field. |
| typedef std::pair<SourceLocation, bool> DeleteExprLoc; |
| typedef llvm::SmallVector<DeleteExprLoc, 4> DeleteLocs; |
| llvm::MapVector<FieldDecl *, DeleteLocs> DeleteExprs; |
| |
| typedef llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy; |
| |
| /// PureVirtualClassDiagSet - a set of class declarations which we have |
| /// emitted a list of pure virtual functions. Used to prevent emitting the |
| /// same list more than once. |
| std::unique_ptr<RecordDeclSetTy> PureVirtualClassDiagSet; |
| |
| /// ParsingInitForAutoVars - a set of declarations with auto types for which |
| /// we are currently parsing the initializer. |
| llvm::SmallPtrSet<const Decl*, 4> ParsingInitForAutoVars; |
| |
| /// Look for a locally scoped extern "C" declaration by the given name. |
| NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name); |
| |
| typedef LazyVector<VarDecl *, ExternalSemaSource, |
| &ExternalSemaSource::ReadTentativeDefinitions, 2, 2> |
| TentativeDefinitionsType; |
| |
| /// All the tentative definitions encountered in the TU. |
| TentativeDefinitionsType TentativeDefinitions; |
| |
| typedef LazyVector<const DeclaratorDecl *, ExternalSemaSource, |
| &ExternalSemaSource::ReadUnusedFileScopedDecls, 2, 2> |
| UnusedFileScopedDeclsType; |
| |
| /// The set of file scoped decls seen so far that have not been used |
| /// and must warn if not used. Only contains the first declaration. |
| UnusedFileScopedDeclsType UnusedFileScopedDecls; |
| |
| typedef LazyVector<CXXConstructorDecl *, ExternalSemaSource, |
| &ExternalSemaSource::ReadDelegatingConstructors, 2, 2> |
| DelegatingCtorDeclsType; |
| |
| /// All the delegating constructors seen so far in the file, used for |
| /// cycle detection at the end of the TU. |
| DelegatingCtorDeclsType DelegatingCtorDecls; |
| |
| /// All the overriding functions seen during a class definition |
| /// that had their exception spec checks delayed, plus the overridden |
| /// function. |
| SmallVector<std::pair<const CXXMethodDecl*, const CXXMethodDecl*>, 2> |
| DelayedOverridingExceptionSpecChecks; |
| |
| /// All the function redeclarations seen during a class definition that had |
| /// their exception spec checks delayed, plus the prior declaration they |
| /// should be checked against. Except during error recovery, the new decl |
| /// should always be a friend declaration, as that's the only valid way to |
| /// redeclare a special member before its class is complete. |
| SmallVector<std::pair<FunctionDecl*, FunctionDecl*>, 2> |
| DelayedEquivalentExceptionSpecChecks; |
| |
| typedef llvm::MapVector<const FunctionDecl *, |
| std::unique_ptr<LateParsedTemplate>> |
| LateParsedTemplateMapT; |
| LateParsedTemplateMapT LateParsedTemplateMap; |
| |
| /// Callback to the parser to parse templated functions when needed. |
| typedef void LateTemplateParserCB(void *P, LateParsedTemplate &LPT); |
| typedef void LateTemplateParserCleanupCB(void *P); |
| LateTemplateParserCB *LateTemplateParser; |
| LateTemplateParserCleanupCB *LateTemplateParserCleanup; |
| void *OpaqueParser; |
| |
| void SetLateTemplateParser(LateTemplateParserCB *LTP, |
| LateTemplateParserCleanupCB *LTPCleanup, |
| void *P) { |
| LateTemplateParser = LTP; |
| LateTemplateParserCleanup = LTPCleanup; |
| OpaqueParser = P; |
| } |
| |
| class DelayedDiagnostics; |
| |
| class DelayedDiagnosticsState { |
| sema::DelayedDiagnosticPool *SavedPool; |
| friend class Sema::DelayedDiagnostics; |
| }; |
| typedef DelayedDiagnosticsState ParsingDeclState; |
| typedef DelayedDiagnosticsState ProcessingContextState; |
| |
| /// A class which encapsulates the logic for delaying diagnostics |
| /// during parsing and other processing. |
| class DelayedDiagnostics { |
| /// The current pool of diagnostics into which delayed |
| /// diagnostics should go. |
| sema::DelayedDiagnosticPool *CurPool; |
| |
| public: |
| DelayedDiagnostics() : CurPool(nullptr) {} |
| |
| /// Adds a delayed diagnostic. |
| void add(const sema::DelayedDiagnostic &diag); // in DelayedDiagnostic.h |
| |
| /// Determines whether diagnostics should be delayed. |
| bool shouldDelayDiagnostics() { return CurPool != nullptr; } |
| |
| /// Returns the current delayed-diagnostics pool. |
| sema::DelayedDiagnosticPool *getCurrentPool() const { |
| return CurPool; |
| } |
| |
| /// Enter a new scope. Access and deprecation diagnostics will be |
| /// collected in this pool. |
| DelayedDiagnosticsState push(sema::DelayedDiagnosticPool &pool) { |
| DelayedDiagnosticsState state; |
| state.SavedPool = CurPool; |
| CurPool = &pool; |
| return state; |
| } |
| |
| /// Leave a delayed-diagnostic state that was previously pushed. |
| /// Do not emit any of the diagnostics. This is performed as part |
| /// of the bookkeeping of popping a pool "properly". |
| void popWithoutEmitting(DelayedDiagnosticsState state) { |
| CurPool = state.SavedPool; |
| } |
| |
| /// Enter a new scope where access and deprecation diagnostics are |
| /// not delayed. |
| DelayedDiagnosticsState pushUndelayed() { |
| DelayedDiagnosticsState state; |
| state.SavedPool = CurPool; |
| CurPool = nullptr; |
| return state; |
| } |
| |
| /// Undo a previous pushUndelayed(). |
| void popUndelayed(DelayedDiagnosticsState state) { |
| assert(CurPool == nullptr); |
| CurPool = state.SavedPool; |
| } |
| } DelayedDiagnostics; |
| |
| /// A RAII object to temporarily push a declaration context. |
| class ContextRAII { |
| private: |
| Sema &S; |
| DeclContext *SavedContext; |
| ProcessingContextState SavedContextState; |
| QualType SavedCXXThisTypeOverride; |
| |
| public: |
| ContextRAII(Sema &S, DeclContext *ContextToPush, bool NewThisContext = true) |
| : S(S), SavedContext(S.CurContext), |
| SavedContextState(S.DelayedDiagnostics.pushUndelayed()), |
| SavedCXXThisTypeOverride(S.CXXThisTypeOverride) |
| { |
| assert(ContextToPush && "pushing null context"); |
| S.CurContext = ContextToPush; |
| if (NewThisContext) |
| S.CXXThisTypeOverride = QualType(); |
| } |
| |
| void pop() { |
| if (!SavedContext) return; |
| S.CurContext = SavedContext; |
| S.DelayedDiagnostics.popUndelayed(SavedContextState); |
| S.CXXThisTypeOverride = SavedCXXThisTypeOverride; |
| SavedContext = nullptr; |
| } |
| |
| ~ContextRAII() { |
| pop(); |
| } |
| }; |
| |
| /// Used to change context to isConstantEvaluated without pushing a heavy |
| /// ExpressionEvaluationContextRecord object. |
| bool isConstantEvaluatedOverride; |
| |
| bool isConstantEvaluated() { |
| return ExprEvalContexts.back().isConstantEvaluated() || |
| isConstantEvaluatedOverride; |
| } |
| |
| /// RAII object to handle the state changes required to synthesize |
| /// a function body. |
| class SynthesizedFunctionScope { |
| Sema &S; |
| Sema::ContextRAII SavedContext; |
| bool PushedCodeSynthesisContext = false; |
| |
| public: |
| SynthesizedFunctionScope(Sema &S, DeclContext *DC) |
| : S(S), SavedContext(S, DC) { |
| S.PushFunctionScope(); |
| S.PushExpressionEvaluationContext( |
| Sema::ExpressionEvaluationContext::PotentiallyEvaluated); |
| if (auto *FD = dyn_cast<FunctionDecl>(DC)) |
| FD->setWillHaveBody(true); |
| else |
| assert(isa<ObjCMethodDecl>(DC)); |
| } |
| |
| void addContextNote(SourceLocation UseLoc) { |
| assert(!PushedCodeSynthesisContext); |
| |
| Sema::CodeSynthesisContext Ctx; |
| Ctx.Kind = Sema::CodeSynthesisContext::DefiningSynthesizedFunction; |
| Ctx.PointOfInstantiation = UseLoc; |
| Ctx.Entity = cast<Decl>(S.CurContext); |
| S.pushCodeSynthesisContext(Ctx); |
| |
| PushedCodeSynthesisContext = true; |
| } |
| |
| ~SynthesizedFunctionScope() { |
| if (PushedCodeSynthesisContext) |
| S.popCodeSynthesisContext(); |
| if (auto *FD = dyn_cast<FunctionDecl>(S.CurContext)) |
| FD->setWillHaveBody(false); |
| S.PopExpressionEvaluationContext(); |
| S.PopFunctionScopeInfo(); |
| } |
| }; |
| |
| /// WeakUndeclaredIdentifiers - Identifiers contained in |
| /// \#pragma weak before declared. rare. may alias another |
| /// identifier, declared or undeclared |
| llvm::MapVector<IdentifierInfo *, WeakInfo> WeakUndeclaredIdentifiers; |
| |
| /// ExtnameUndeclaredIdentifiers - Identifiers contained in |
| /// \#pragma redefine_extname before declared. Used in Solaris system headers |
| /// to define functions that occur in multiple standards to call the version |
| /// in the currently selected standard. |
| llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*> ExtnameUndeclaredIdentifiers; |
| |
| |
| /// Load weak undeclared identifiers from the external source. |
| void LoadExternalWeakUndeclaredIdentifiers(); |
| |
| /// WeakTopLevelDecl - Translation-unit scoped declarations generated by |
| /// \#pragma weak during processing of other Decls. |
| /// I couldn't figure out a clean way to generate these in-line, so |
| /// we store them here and handle separately -- which is a hack. |
| /// It would be best to refactor this. |
| SmallVector<Decl*,2> WeakTopLevelDecl; |
| |
| IdentifierResolver IdResolver; |
| |
| /// Translation Unit Scope - useful to Objective-C actions that need |
| /// to lookup file scope declarations in the "ordinary" C decl namespace. |
| /// For example, user-defined classes, built-in "id" type, etc. |
| Scope *TUScope; |
| |
| /// The C++ "std" namespace, where the standard library resides. |
| LazyDeclPtr StdNamespace; |
| |
| /// The C++ "std::bad_alloc" class, which is defined by the C++ |
| /// standard library. |
| LazyDeclPtr StdBadAlloc; |
| |
| /// The C++ "std::align_val_t" enum class, which is defined by the C++ |
| /// standard library. |
| LazyDeclPtr StdAlignValT; |
| |
| /// The C++ "std::experimental" namespace, where the experimental parts |
| /// of the standard library resides. |
| NamespaceDecl *StdExperimentalNamespaceCache; |
| |
| /// The C++ "std::initializer_list" template, which is defined in |
| /// \<initializer_list>. |
| ClassTemplateDecl *StdInitializerList; |
| |
| /// The C++ "std::coroutine_traits" template, which is defined in |
| /// \<coroutine_traits> |
| ClassTemplateDecl *StdCoroutineTraitsCache; |
| |
| /// The C++ "type_info" declaration, which is defined in \<typeinfo>. |
| RecordDecl *CXXTypeInfoDecl; |
| |
| /// The MSVC "_GUID" struct, which is defined in MSVC header files. |
| RecordDecl *MSVCGuidDecl; |
| |
| /// Caches identifiers/selectors for NSFoundation APIs. |
| std::unique_ptr<NSAPI> NSAPIObj; |
| |
| /// The declaration of the Objective-C NSNumber class. |
| ObjCInterfaceDecl *NSNumberDecl; |
| |
| /// The declaration of the Objective-C NSValue class. |
| ObjCInterfaceDecl *NSValueDecl; |
| |
| /// Pointer to NSNumber type (NSNumber *). |
| QualType NSNumberPointer; |
| |
| /// Pointer to NSValue type (NSValue *). |
| QualType NSValuePointer; |
| |
| /// The Objective-C NSNumber methods used to create NSNumber literals. |
| ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods]; |
| |
| /// The declaration of the Objective-C NSString class. |
| ObjCInterfaceDecl *NSStringDecl; |
| |
| /// Pointer to NSString type (NSString *). |
| QualType NSStringPointer; |
| |
| /// The declaration of the stringWithUTF8String: method. |
| ObjCMethodDecl *StringWithUTF8StringMethod; |
| |
| /// The declaration of the valueWithBytes:objCType: method. |
| ObjCMethodDecl *ValueWithBytesObjCTypeMethod; |
| |
| /// The declaration of the Objective-C NSArray class. |
| ObjCInterfaceDecl *NSArrayDecl; |
| |
| /// The declaration of the arrayWithObjects:count: method. |
| ObjCMethodDecl *ArrayWithObjectsMethod; |
| |
| /// The declaration of the Objective-C NSDictionary class. |
| ObjCInterfaceDecl *NSDictionaryDecl; |
| |
| /// The declaration of the dictionaryWithObjects:forKeys:count: method. |
| ObjCMethodDecl *DictionaryWithObjectsMethod; |
| |
| /// id<NSCopying> type. |
| QualType QIDNSCopying; |
| |
| /// will hold 'respondsToSelector:' |
| Selector RespondsToSelectorSel; |
| |
| /// A flag to remember whether the implicit forms of operator new and delete |
| /// have been declared. |
| bool GlobalNewDeleteDeclared; |
| |
| /// A flag to indicate that we're in a context that permits abstract |
| /// references to fields. This is really a |
| bool AllowAbstractFieldReference; |
| |
| /// Describes how the expressions currently being parsed are |
| /// evaluated at run-time, if at all. |
| enum class ExpressionEvaluationContext { |
| /// The current expression and its subexpressions occur within an |
| /// unevaluated operand (C++11 [expr]p7), such as the subexpression of |
| /// \c sizeof, where the type of the expression may be significant but |
| /// no code will be generated to evaluate the value of the expression at |
| /// run time. |
| Unevaluated, |
| |
| /// The current expression occurs within a braced-init-list within |
| /// an unevaluated operand. This is mostly like a regular unevaluated |
| /// context, except that we still instantiate constexpr functions that are |
| /// referenced here so that we can perform narrowing checks correctly. |
| UnevaluatedList, |
| |
| /// The current expression occurs within a discarded statement. |
| /// This behaves largely similarly to an unevaluated operand in preventing |
| /// definitions from being required, but not in other ways. |
| DiscardedStatement, |
| |
| /// The current expression occurs within an unevaluated |
| /// operand that unconditionally permits abstract references to |
| /// fields, such as a SIZE operator in MS-style inline assembly. |
| UnevaluatedAbstract, |
| |
| /// The current context is "potentially evaluated" in C++11 terms, |
| /// but the expression is evaluated at compile-time (like the values of |
| /// cases in a switch statement). |
| ConstantEvaluated, |
| |
| /// The current expression is potentially evaluated at run time, |
| /// which means that code may be generated to evaluate the value of the |
| /// expression at run time. |
| PotentiallyEvaluated, |
| |
| /// The current expression is potentially evaluated, but any |
| /// declarations referenced inside that expression are only used if |
| /// in fact the current expression is used. |
| /// |
| /// This value is used when parsing default function arguments, for which |
| /// we would like to provide diagnostics (e.g., passing non-POD arguments |
| /// through varargs) but do not want to mark declarations as "referenced" |
| /// until the default argument is used. |
| PotentiallyEvaluatedIfUsed |
| }; |
| |
| /// Data structure used to record current or nested |
| /// expression evaluation contexts. |
| struct ExpressionEvaluationContextRecord { |
| /// The expression evaluation context. |
| ExpressionEvaluationContext Context; |
| |
| /// Whether the enclosing context needed a cleanup. |
| CleanupInfo ParentCleanup; |
| |
| /// Whether we are in a decltype expression. |
| bool IsDecltype; |
| |
| /// The number of active cleanup objects when we entered |
| /// this expression evaluation context. |
| unsigned NumCleanupObjects; |
| |
| /// The number of typos encountered during this expression evaluation |
| /// context (i.e. the number of TypoExprs created). |
| unsigned NumTypos; |
| |
| MaybeODRUseExprSet SavedMaybeODRUseExprs; |
| |
| /// The lambdas that are present within this context, if it |
| /// is indeed an unevaluated context. |
| SmallVector<LambdaExpr *, 2> Lambdas; |
| |
| /// The declaration that provides context for lambda expressions |
| /// and block literals if the normal declaration context does not |
| /// suffice, e.g., in a default function argument. |
| Decl *ManglingContextDecl; |
| |
| /// If we are processing a decltype type, a set of call expressions |
| /// for which we have deferred checking the completeness of the return type. |
| SmallVector<CallExpr *, 8> DelayedDecltypeCalls; |
| |
| /// If we are processing a decltype type, a set of temporary binding |
| /// expressions for which we have deferred checking the destructor. |
| SmallVector<CXXBindTemporaryExpr *, 8> DelayedDecltypeBinds; |
| |
| llvm::SmallPtrSet<const Expr *, 8> PossibleDerefs; |
| |
| /// Expressions appearing as the LHS of a volatile assignment in this |
| /// context. We produce a warning for these when popping the context if |
| /// they are not discarded-value expressions nor unevaluated operands. |
| SmallVector<Expr*, 2> VolatileAssignmentLHSs; |
| |
| /// \brief Describes whether we are in an expression constext which we have |
| /// to handle differently. |
| enum ExpressionKind { |
| EK_Decltype, EK_TemplateArgument, EK_Other |
| } ExprContext; |
| |
| ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, |
| unsigned NumCleanupObjects, |
| CleanupInfo ParentCleanup, |
| Decl *ManglingContextDecl, |
| ExpressionKind ExprContext) |
| : Context(Context), ParentCleanup(ParentCleanup), |
| NumCleanupObjects(NumCleanupObjects), NumTypos(0), |
| ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext) {} |
| |
| bool isUnevaluated() const { |
| return Context == ExpressionEvaluationContext::Unevaluated || |
| Context == ExpressionEvaluationContext::UnevaluatedAbstract || |
| Context == ExpressionEvaluationContext::UnevaluatedList; |
| } |
| bool isConstantEvaluated() const { |
| return Context == ExpressionEvaluationContext::ConstantEvaluated; |
| } |
| }; |
| |
| /// A stack of expression evaluation contexts. |
| SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts; |
| |
| /// Emit a warning for all pending noderef expressions that we recorded. |
| void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec); |
| |
| /// Compute the mangling number context for a lambda expression or |
| /// block literal. Also return the extra mangling decl if any. |
| /// |
| /// \param DC - The DeclContext containing the lambda expression or |
| /// block literal. |
| std::tuple<MangleNumberingContext *, Decl *> |
| getCurrentMangleNumberContext(const DeclContext *DC); |
| |
| |
| /// SpecialMemberOverloadResult - The overloading result for a special member |
| /// function. |
| /// |
| /// This is basically a wrapper around PointerIntPair. The lowest bits of the |
| /// integer are used to determine whether overload resolution succeeded. |
| class SpecialMemberOverloadResult { |
| public: |
| enum Kind { |
| NoMemberOrDeleted, |
| Ambiguous, |
| Success |
| }; |
| |
| private: |
| llvm::PointerIntPair<CXXMethodDecl*, 2> Pair; |
| |
| public: |
| SpecialMemberOverloadResult() : Pair() {} |
| SpecialMemberOverloadResult(CXXMethodDecl *MD) |
| : Pair(MD, MD->isDeleted() ? NoMemberOrDeleted : Success) {} |
| |
| CXXMethodDecl *getMethod() const { return Pair.getPointer(); } |
| void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); } |
| |
| Kind getKind() const { return static_cast<Kind>(Pair.getInt()); } |
| void setKind(Kind K) { Pair.setInt(K); } |
| }; |
| |
| class SpecialMemberOverloadResultEntry |
| : public llvm::FastFoldingSetNode, |
| public SpecialMemberOverloadResult { |
| public: |
| SpecialMemberOverloadResultEntry(const llvm::FoldingSetNodeID &ID) |
| : FastFoldingSetNode(ID) |
| {} |
| }; |
| |
| /// A cache of special member function overload resolution results |
| /// for C++ records. |
| llvm::FoldingSet<SpecialMemberOverloadResultEntry> SpecialMemberCache; |
| |
| /// A cache of the flags available in enumerations with the flag_bits |
| /// attribute. |
| mutable llvm::DenseMap<const EnumDecl*, llvm::APInt> FlagBitsCache; |
| |
| /// The kind of translation unit we are processing. |
| /// |
| /// When we're processing a complete translation unit, Sema will perform |
| /// end-of-translation-unit semantic tasks (such as creating |
| /// initializers for tentative definitions in C) once parsing has |
| /// completed. Modules and precompiled headers perform different kinds of |
| /// checks. |
| TranslationUnitKind TUKind; |
| |
| llvm::BumpPtrAllocator BumpAlloc; |
| |
| /// The number of SFINAE diagnostics that have been trapped. |
| unsigned NumSFINAEErrors; |
| |
| typedef llvm::DenseMap<ParmVarDecl *, llvm::TinyPtrVector<ParmVarDecl *>> |
| UnparsedDefaultArgInstantiationsMap; |
| |
| /// A mapping from parameters with unparsed default arguments to the |
| /// set of instantiations of each parameter. |
| /// |
| /// This mapping is a temporary data structure used when parsing |
| /// nested class templates or nested classes of class templates, |
| /// where we might end up instantiating an inner class before the |
| /// default arguments of its methods have been parsed. |
| UnparsedDefaultArgInstantiationsMap UnparsedDefaultArgInstantiations; |
| |
| // Contains the locations of the beginning of unparsed default |
| // argument locations. |
| llvm::DenseMap<ParmVarDecl *, SourceLocation> UnparsedDefaultArgLocs; |
| |
| /// UndefinedInternals - all the used, undefined objects which require a |
| /// definition in this translation unit. |
| llvm::MapVector<NamedDecl *, SourceLocation> UndefinedButUsed; |
| |
| /// Determine if VD, which must be a variable or function, is an external |
| /// symbol that nonetheless can't be referenced from outside this translation |
| /// unit because its type has no linkage and it's not extern "C". |
| bool isExternalWithNoLinkageType(ValueDecl *VD); |
| |
| /// Obtain a sorted list of functions that are undefined but ODR-used. |
| void getUndefinedButUsed( |
| SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined); |
| |
| /// Retrieves list of suspicious delete-expressions that will be checked at |
| /// the end of translation unit. |
| const llvm::MapVector<FieldDecl *, DeleteLocs> & |
| getMismatchingDeleteExpressions() const; |
| |
| typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods; |
| typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool; |
| |
| /// Method Pool - allows efficient lookup when typechecking messages to "id". |
| /// We need to maintain a list, since selectors can have differing signatures |
| /// across classes. In Cocoa, this happens to be extremely uncommon (only 1% |
| /// of selectors are "overloaded"). |
| /// At the head of the list it is recorded whether there were 0, 1, or >= 2 |
| /// methods inside categories with a particular selector. |
| GlobalMethodPool MethodPool; |
| |
| /// Method selectors used in a \@selector expression. Used for implementation |
| /// of -Wselector. |
| llvm::MapVector<Selector, SourceLocation> ReferencedSelectors; |
| |
| /// List of SourceLocations where 'self' is implicitly retained inside a |
| /// block. |
| llvm::SmallVector<std::pair<SourceLocation, const BlockDecl *>, 1> |
| ImplicitlyRetainedSelfLocs; |
| |
| /// Kinds of C++ special members. |
| enum CXXSpecialMember { |
| CXXDefaultConstructor, |
| CXXCopyConstructor, |
| CXXMoveConstructor, |
| CXXCopyAssignment, |
| CXXMoveAssignment, |
| CXXDestructor, |
| CXXInvalid |
| }; |
| |
| typedef llvm::PointerIntPair<CXXRecordDecl *, 3, CXXSpecialMember> |
| SpecialMemberDecl; |
| |
| /// The C++ special members which we are currently in the process of |
| /// declaring. If this process recursively triggers the declaration of the |
| /// same special member, we should act as if it is not yet declared. |
| llvm::SmallPtrSet<SpecialMemberDecl, 4> SpecialMembersBeingDeclared; |
| |
| /// Kinds of defaulted comparison operator functions. |
| enum class DefaultedComparisonKind : unsigned char { |
| /// This is not a defaultable comparison operator. |
| None, |
| /// This is an operator== that should be implemented as a series of |
| /// subobject comparisons. |
| Equal, |
| /// This is an operator<=> that should be implemented as a series of |
| /// subobject comparisons. |
| ThreeWay, |
| /// This is an operator!= that should be implemented as a rewrite in terms |
| /// of a == comparison. |
| NotEqual, |
| /// This is an <, <=, >, or >= that should be implemented as a rewrite in |
| /// terms of a <=> comparison. |
| Relational, |
| }; |
| |
| /// The function definitions which were renamed as part of typo-correction |
| /// to match their respective declarations. We want to keep track of them |
| /// to ensure that we don't emit a "redefinition" error if we encounter a |
| /// correctly named definition after the renamed definition. |
| llvm::SmallPtrSet<const NamedDecl *, 4> TypoCorrectedFunctionDefinitions; |
| |
| /// Stack of types that correspond to the parameter entities that are |
| /// currently being copy-initialized. Can be empty. |
| llvm::SmallVector<QualType, 4> CurrentParameterCopyTypes; |
| |
| void ReadMethodPool(Selector Sel); |
| void updateOutOfDateSelector(Selector Sel); |
| |
| /// Private Helper predicate to check for 'self'. |
| bool isSelfExpr(Expr *RExpr); |
| bool isSelfExpr(Expr *RExpr, const ObjCMethodDecl *Method); |
| |
| /// Cause the active diagnostic on the DiagosticsEngine to be |
| /// emitted. This is closely coupled to the SemaDiagnosticBuilder class and |
| /// should not be used elsewhere. |
| void EmitCurrentDiagnostic(unsigned DiagID); |
| |
| /// Records and restores the FP_CONTRACT state on entry/exit of compound |
| /// statements. |
| class FPContractStateRAII { |
| public: |
| FPContractStateRAII(Sema &S) : S(S), OldFPFeaturesState(S.FPFeatures) {} |
| ~FPContractStateRAII() { S.FPFeatures = OldFPFeaturesState; } |
| |
| private: |
| Sema& S; |
| FPOptions OldFPFeaturesState; |
| }; |
| |
| void addImplicitTypedef(StringRef Name, QualType T); |
| |
| bool WarnedStackExhausted = false; |
| |
| public: |
| Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, |
| TranslationUnitKind TUKind = TU_Complete, |
| CodeCompleteConsumer *CompletionConsumer = nullptr); |
| ~Sema(); |
| |
| /// Perform initialization that occurs after the parser has been |
| /// initialized but before it parses anything. |
| void Initialize(); |
| |
| const LangOptions &getLangOpts() const { return LangOpts; } |
| OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; } |
| FPOptions &getFPOptions() { return FPFeatures; } |
| |
| DiagnosticsEngine &getDiagnostics() const { return Diags; } |
| SourceManager &getSourceManager() const { return SourceMgr; } |
| Preprocessor &getPreprocessor() const { return PP; } |
| ASTContext &getASTContext() const { return Context; } |
| ASTConsumer &getASTConsumer() const { return Consumer; } |
| ASTMutationListener *getASTMutationListener() const; |
| ExternalSemaSource* getExternalSource() const { return ExternalSource; } |
| |
| ///Registers an external source. If an external source already exists, |
| /// creates a multiplex external source and appends to it. |
| /// |
| ///\param[in] E - A non-null external sema source. |
| /// |
| void addExternalSource(ExternalSemaSource *E); |
| |
| void PrintStats() const; |
| |
| /// Warn that the stack is nearly exhausted. |
| void warnStackExhausted(SourceLocation Loc); |
| |
| /// Run some code with "sufficient" stack space. (Currently, at least 256K is |
| /// guaranteed). Produces a warning if we're low on stack space and allocates |
| /// more in that case. Use this in code that may recurse deeply (for example, |
| /// in template instantiation) to avoid stack overflow. |
| void runWithSufficientStackSpace(SourceLocation Loc, |
| llvm::function_ref<void()> Fn); |
| |
| /// Helper class that creates diagnostics with optional |
| /// template instantiation stacks. |
| /// |
| /// This class provides a wrapper around the basic DiagnosticBuilder |
| /// class that emits diagnostics. SemaDiagnosticBuilder is |
| /// responsible for emitting the diagnostic (as DiagnosticBuilder |
| /// does) and, if the diagnostic comes from inside a template |
| /// instantiation, printing the template instantiation stack as |
| /// well. |
| class SemaDiagnosticBuilder : public DiagnosticBuilder { |
| Sema &SemaRef; |
| unsigned DiagID; |
| |
| public: |
| SemaDiagnosticBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID) |
| : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) { } |
| |
| // This is a cunning lie. DiagnosticBuilder actually performs move |
| // construction in its copy constructor (but due to varied uses, it's not |
| // possible to conveniently express this as actual move construction). So |
| // the default copy ctor here is fine, because the base class disables the |
| // source anyway, so the user-defined ~SemaDiagnosticBuilder is a safe no-op |
| // in that case anwyay. |
| SemaDiagnosticBuilder(const SemaDiagnosticBuilder&) = default; |
| |
| ~SemaDiagnosticBuilder() { |
| // If we aren't active, there is nothing to do. |
| if (!isActive()) return; |
| |
| // Otherwise, we need to emit the diagnostic. First flush the underlying |
| // DiagnosticBuilder data, and clear the diagnostic builder itself so it |
| // won't emit the diagnostic in its own destructor. |
| // |
| // This seems wasteful, in that as written the DiagnosticBuilder dtor will |
| // do its own needless checks to see if the diagnostic needs to be |
| // emitted. However, because we take care to ensure that the builder |
| // objects never escape, a sufficiently smart compiler will be able to |
| // eliminate that code. |
| FlushCounts(); |
| Clear(); |
| |
| // Dispatch to Sema to emit the diagnostic. |
| SemaRef.EmitCurrentDiagnostic(DiagID); |
| } |
| |
| /// Teach operator<< to produce an object of the correct type. |
| template<typename T> |
| friend const SemaDiagnosticBuilder &operator<<( |
| const SemaDiagnosticBuilder &Diag, const T &Value) { |
| const DiagnosticBuilder &BaseDiag = Diag; |
| BaseDiag << Value; |
| return Diag; |
| } |
| }; |
| |
| /// Emit a diagnostic. |
| SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { |
| DiagnosticBuilder DB = Diags.Report(Loc, DiagID); |
| return SemaDiagnosticBuilder(DB, *this, DiagID); |
| } |
| |
| /// Emit a partial diagnostic. |
| SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic& PD); |
| |
| /// Build a partial diagnostic. |
| PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h |
| |
| bool findMacroSpelling(SourceLocation &loc, StringRef name); |
| |
| /// Get a string to suggest for zero-initialization of a type. |
| std::string |
| getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const; |
| std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const; |
| |
| /// Calls \c Lexer::getLocForEndOfToken() |
| SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0); |
| |
| /// Retrieve the module loader associated with the preprocessor. |
| ModuleLoader &getModuleLoader() const; |
| |
| void emitAndClearUnusedLocalTypedefWarnings(); |
| |
| enum TUFragmentKind { |
| /// The global module fragment, between 'module;' and a module-declaration. |
| Global, |
| /// A normal translation unit fragment. For a non-module unit, this is the |
| /// entire translation unit. Otherwise, it runs from the module-declaration |
| /// to the private-module-fragment (if any) or the end of the TU (if not). |
| Normal, |
| /// The private module fragment, between 'module :private;' and the end of |
| /// the translation unit. |
| Private |
| }; |
| |
| void ActOnStartOfTranslationUnit(); |
| void ActOnEndOfTranslationUnit(); |
| void ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind); |
| |
| void CheckDelegatingCtorCycles(); |
| |
| Scope *getScopeForContext(DeclContext *Ctx); |
| |
| void PushFunctionScope(); |
| void PushBlockScope(Scope *BlockScope, BlockDecl *Block); |
| sema::LambdaScopeInfo *PushLambdaScope(); |
| |
| /// This is used to inform Sema what the current TemplateParameterDepth |
| /// is during Parsing. Currently it is used to pass on the depth |
| /// when parsing generic lambda 'auto' parameters. |
| void RecordParsingTemplateParameterDepth(unsigned Depth); |
| |
| void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD, |
| RecordDecl *RD, CapturedRegionKind K, |
| unsigned OpenMPCaptureLevel = 0); |
| |
| /// Custom deleter to allow FunctionScopeInfos to be kept alive for a short |
| /// time after they've been popped. |
| class PoppedFunctionScopeDeleter { |
| Sema *Self; |
| |
| public: |
| explicit PoppedFunctionScopeDeleter(Sema *Self) : Self(Self) {} |
| void operator()(sema::FunctionScopeInfo *Scope) const; |
| }; |
| |
| using PoppedFunctionScopePtr = |
| std::unique_ptr<sema::FunctionScopeInfo, PoppedFunctionScopeDeleter>; |
| |
| PoppedFunctionScopePtr |
| PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP = nullptr, |
| const Decl *D = nullptr, |
| QualType BlockType = QualType()); |
| |
| sema::FunctionScopeInfo *getCurFunction() const { |
| return FunctionScopes.empty() ? nullptr : FunctionScopes.back(); |
| } |
| |
| sema::FunctionScopeInfo *getEnclosingFunction() const; |
| |
| void setFunctionHasBranchIntoScope(); |
| void setFunctionHasBranchProtectedScope(); |
| void setFunctionHasIndirectGoto(); |
| |
| void PushCompoundScope(bool IsStmtExpr); |
| void PopCompoundScope(); |
| |
| sema::CompoundScopeInfo &getCurCompoundScope() const; |
| |
| bool hasAnyUnrecoverableErrorsInThisFunction() const; |
| |
| /// Retrieve the current block, if any. |
| sema::BlockScopeInfo *getCurBlock(); |
| |
| /// Get the innermost lambda enclosing the current location, if any. This |
| /// looks through intervening non-lambda scopes such as local functions and |
| /// blocks. |
| sema::LambdaScopeInfo *getEnclosingLambda() const; |
| |
| /// Retrieve the current lambda scope info, if any. |
| /// \param IgnoreNonLambdaCapturingScope true if should find the top-most |
| /// lambda scope info ignoring all inner capturing scopes that are not |
| /// lambda scopes. |
| sema::LambdaScopeInfo * |
| getCurLambda(bool IgnoreNonLambdaCapturingScope = false); |
| |
| /// Retrieve the current generic lambda info, if any. |
| sema::LambdaScopeInfo *getCurGenericLambda(); |
| |
| /// Retrieve the current captured region, if any. |
| sema::CapturedRegionScopeInfo *getCurCapturedRegion(); |
| |
| /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls |
| SmallVectorImpl<Decl *> &WeakTopLevelDecls() { return WeakTopLevelDecl; } |
| |
| void ActOnComment(SourceRange Comment); |
| |
| //===--------------------------------------------------------------------===// |
| // Type Analysis / Processing: SemaType.cpp. |
| // |
| |
| QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs, |
| const DeclSpec *DS = nullptr); |
| QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVRA, |
| const DeclSpec *DS = nullptr); |
| QualType BuildPointerType(QualType T, |
| SourceLocation Loc, DeclarationName Entity); |
| QualType BuildReferenceType(QualType T, bool LValueRef, |
| SourceLocation Loc, DeclarationName Entity); |
| QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, |
| Expr *ArraySize, unsigned Quals, |
| SourceRange Brackets, DeclarationName Entity); |
| QualType BuildVectorType(QualType T, Expr *VecSize, SourceLocation AttrLoc); |
| QualType BuildExtVectorType(QualType T, Expr *ArraySize, |
| SourceLocation AttrLoc); |
| QualType BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace, |
| SourceLocation AttrLoc); |
| |
| /// Same as above, but constructs the AddressSpace index if not provided. |
| QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, |
| SourceLocation AttrLoc); |
| |
| bool CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc); |
| |
| bool CheckFunctionReturnType(QualType T, SourceLocation Loc); |
| |
| /// Build a function type. |
| /// |
| /// This routine checks the function type according to C++ rules and |
| /// under the assumption that the result type and parameter types have |
| /// just been instantiated from a template. It therefore duplicates |
| /// some of the behavior of GetTypeForDeclarator, but in a much |
| /// simpler form that is only suitable for this narrow use case. |
| /// |
| /// \param T The return type of the function. |
| /// |
| /// \param ParamTypes The parameter types of the function. This array |
| /// will be modified to account for adjustments to the types of the |
| /// function parameters. |
| /// |
| /// \param Loc The location of the entity whose type involves this |
| /// function type or, if there is no such entity, the location of the |
| /// type that will have function type. |
| /// |
| /// \param Entity The name of the entity that involves the function |
| /// type, if known. |
| /// |
| /// \param EPI Extra information about the function type. Usually this will |
| /// be taken from an existing function with the same prototype. |
| /// |
| /// \returns A suitable function type, if there are no errors. The |
| /// unqualified type will always be a FunctionProtoType. |
| /// Otherwise, returns a NULL type. |
| QualType BuildFunctionType(QualType T, |
| MutableArrayRef<QualType> ParamTypes, |
| SourceLocation Loc, DeclarationName Entity, |
| const FunctionProtoType::ExtProtoInfo &EPI); |
| |
| QualType BuildMemberPointerType(QualType T, QualType Class, |
| SourceLocation Loc, |
| DeclarationName Entity); |
| QualType BuildBlockPointerType(QualType T, |
| SourceLocation Loc, DeclarationName Entity); |
| QualType BuildParenType(QualType T); |
| QualType BuildAtomicType(QualType T, SourceLocation Loc); |
| QualType BuildReadPipeType(QualType T, |
| SourceLocation Loc); |
| QualType BuildWritePipeType(QualType T, |
| SourceLocation Loc); |
| |
| TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S); |
| TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy); |
| |
| /// Package the given type and TSI into a ParsedType. |
| ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo); |
| DeclarationNameInfo GetNameForDeclarator(Declarator &D); |
| DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name); |
| static QualType GetTypeFromParser(ParsedType Ty, |
| TypeSourceInfo **TInfo = nullptr); |
| CanThrowResult canThrow(const Expr *E); |
| const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc, |
| const FunctionProtoType *FPT); |
| void UpdateExceptionSpec(FunctionDecl *FD, |
| const FunctionProtoType::ExceptionSpecInfo &ESI); |
| bool CheckSpecifiedExceptionType(QualType &T, SourceRange Range); |
| bool CheckDistantExceptionSpec(QualType T); |
| bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New); |
| bool CheckEquivalentExceptionSpec( |
| const FunctionProtoType *Old, SourceLocation OldLoc, |
| const FunctionProtoType *New, SourceLocation NewLoc); |
| bool CheckEquivalentExceptionSpec( |
| const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, |
| const FunctionProtoType *Old, SourceLocation OldLoc, |
| const FunctionProtoType *New, SourceLocation NewLoc); |
| bool handlerCanCatch(QualType HandlerType, QualType ExceptionType); |
| bool CheckExceptionSpecSubset(const PartialDiagnostic &DiagID, |
| const PartialDiagnostic &NestedDiagID, |
| const PartialDiagnostic &NoteID, |
| const PartialDiagnostic &NoThrowDiagID, |
| const FunctionProtoType *Superset, |
| SourceLocation SuperLoc, |
| const FunctionProtoType *Subset, |
| SourceLocation SubLoc); |
| bool CheckParamExceptionSpec(const PartialDiagnostic &NestedDiagID, |
| const PartialDiagnostic &NoteID, |
| const FunctionProtoType *Target, |
| SourceLocation TargetLoc, |
| const FunctionProtoType *Source, |
| SourceLocation SourceLoc); |
| |
| TypeResult ActOnTypeName(Scope *S, Declarator &D); |
| |
| /// The parser has parsed the context-sensitive type 'instancetype' |
| /// in an Objective-C message declaration. Return the appropriate type. |
| ParsedType ActOnObjCInstanceType(SourceLocation Loc); |
| |
| /// Abstract class used to diagnose incomplete types. |
| struct TypeDiagnoser { |
| TypeDiagnoser() {} |
| |
| virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0; |
| virtual ~TypeDiagnoser() {} |
| }; |
| |
| static int getPrintable(int I) { return I; } |
| static unsigned getPrintable(unsigned I) { return I; } |
| static bool getPrintable(bool B) { return B; } |
| static const char * getPrintable(const char *S) { return S; } |
| static StringRef getPrintable(StringRef S) { return S; } |
| static const std::string &getPrintable(const std::string &S) { return S; } |
| static const IdentifierInfo *getPrintable(const IdentifierInfo *II) { |
| return II; |
| } |
| static DeclarationName getPrintable(DeclarationName N) { return N; } |
| static QualType getPrintable(QualType T) { return T; } |
| static SourceRange getPrintable(SourceRange R) { return R; } |
| static SourceRange getPrintable(SourceLocation L) { return L; } |
| static SourceRange getPrintable(const Expr *E) { return E->getSourceRange(); } |
| static SourceRange getPrintable(TypeLoc TL) { return TL.getSourceRange();} |
| |
| template <typename... Ts> class BoundTypeDiagnoser : public TypeDiagnoser { |
| unsigned DiagID; |
| std::tuple<const Ts &...> Args; |
| |
| template <std::size_t... Is> |
| void emit(const SemaDiagnosticBuilder &DB, |
| std::index_sequence<Is...>) const { |
| // Apply all tuple elements to the builder in order. |
| bool Dummy[] = {false, (DB << getPrintable(std::get<Is>(Args)))...}; |
| (void)Dummy; |
| } |
| |
| public: |
| BoundTypeDiagnoser(unsigned DiagID, const Ts &...Args) |
| : TypeDiagnoser(), DiagID(DiagID), Args(Args...) { |
| assert(DiagID != 0 && "no diagnostic for type diagnoser"); |
| } |
| |
| void diagnose(Sema &S, SourceLocation Loc, QualType T) override { |
| const SemaDiagnosticBuilder &DB = S.Diag(Loc, DiagID); |
| emit(DB, std::index_sequence_for<Ts...>()); |
| DB << T; |
| } |
| }; |
| |
| private: |
| /// Methods for marking which expressions involve dereferencing a pointer |
| /// marked with the 'noderef' attribute. Expressions are checked bottom up as |
| /// they are parsed, meaning that a noderef pointer may not be accessed. For |
| /// example, in `&*p` where `p` is a noderef pointer, we will first parse the |
| /// `*p`, but need to check that `address of` is called on it. This requires |
| /// keeping a container of all pending expressions and checking if the address |
| /// of them are eventually taken. |
| void CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E); |
| void CheckAddressOfNoDeref(const Expr *E); |
| void CheckMemberAccessOfNoDeref(const MemberExpr *E); |
| |
| bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T, |
| TypeDiagnoser *Diagnoser); |
| |
| struct ModuleScope { |
| SourceLocation BeginLoc; |
| clang::Module *Module = nullptr; |
| bool ModuleInterface = false; |
| bool ImplicitGlobalModuleFragment = false; |
| VisibleModuleSet OuterVisibleModules; |
| }; |
| /// The modules we're currently parsing. |
| llvm::SmallVector<ModuleScope, 16> ModuleScopes; |
| |
| /// Namespace definitions that we will export when they finish. |
| llvm::SmallPtrSet<const NamespaceDecl*, 8> DeferredExportedNamespaces; |
| |
| /// Get the module whose scope we are currently within. |
| Module *getCurrentModule() const { |
| return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module; |
| } |
| |
| VisibleModuleSet VisibleModules; |
| |
| public: |
| /// Get the module owning an entity. |
| Module *getOwningModule(Decl *Entity) { return Entity->getOwningModule(); } |
| |
| /// Make a merged definition of an existing hidden definition \p ND |
| /// visible at the specified location. |
| void makeMergedDefinitionVisible(NamedDecl *ND); |
| |
| bool isModuleVisible(const Module *M, bool ModulePrivate = false); |
| |
| /// Determine whether a declaration is visible to name lookup. |
| bool isVisible(const NamedDecl *D) { |
| return !D->isHidden() || isVisibleSlow(D); |
| } |
| |
| /// Determine whether any declaration of an entity is visible. |
| bool |
| hasVisibleDeclaration(const NamedDecl *D, |
| llvm::SmallVectorImpl<Module *> *Modules = nullptr) { |
| return isVisible(D) || hasVisibleDeclarationSlow(D, Modules); |
| } |
| bool hasVisibleDeclarationSlow(const NamedDecl *D, |
| llvm::SmallVectorImpl<Module *> *Modules); |
| |
| bool hasVisibleMergedDefinition(NamedDecl *Def); |
| bool hasMergedDefinitionInCurrentModule(NamedDecl *Def); |
| |
| /// Determine if \p D and \p Suggested have a structurally compatible |
| /// layout as described in C11 6.2.7/1. |
| bool hasStructuralCompatLayout(Decl *D, Decl *Suggested); |
| |
| /// Determine if \p D has a visible definition. If not, suggest a declaration |
| /// that should be made visible to expose the definition. |
| bool hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested, |
| bool OnlyNeedComplete = false); |
| bool hasVisibleDefinition(const NamedDecl *D) { |
| NamedDecl *Hidden; |
| return hasVisibleDefinition(const_cast<NamedDecl*>(D), &Hidden); |
| } |
| |
| /// Determine if the template parameter \p D has a visible default argument. |
| bool |
| hasVisibleDefaultArgument(const NamedDecl *D, |
| llvm::SmallVectorImpl<Module *> *Modules = nullptr); |
| |
| /// Determine if there is a visible declaration of \p D that is an explicit |
| /// specialization declaration for a specialization of a template. (For a |
| /// member specialization, use hasVisibleMemberSpecialization.) |
| bool hasVisibleExplicitSpecialization( |
| const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules = nullptr); |
| |
| /// Determine if there is a visible declaration of \p D that is a member |
| /// specialization declaration (as opposed to an instantiated declaration). |
| bool hasVisibleMemberSpecialization( |
| const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules = nullptr); |
| |
| /// Determine if \p A and \p B are equivalent internal linkage declarations |
| /// from different modules, and thus an ambiguity error can be downgraded to |
| /// an extension warning. |
| bool isEquivalentInternalLinkageDeclaration(const NamedDecl *A, |
| const NamedDecl *B); |
| void diagnoseEquivalentInternalLinkageDeclarations( |
| SourceLocation Loc, const NamedDecl *D, |
| ArrayRef<const NamedDecl *> Equiv); |
| |
| bool isUsualDeallocationFunction(const CXXMethodDecl *FD); |
| |
| bool isCompleteType(SourceLocation Loc, QualType T) { |
| return !RequireCompleteTypeImpl(Loc, T, nullptr); |
| } |
| bool RequireCompleteType(SourceLocation Loc, QualType T, |
| TypeDiagnoser &Diagnoser); |
| bool RequireCompleteType(SourceLocation Loc, QualType T, |
| unsigned DiagID); |
| |
| template <typename... Ts> |
| bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID, |
| const Ts &...Args) { |
| BoundTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...); |
| return RequireCompleteType(Loc, T, Diagnoser); |
| } |
| |
| void completeExprArrayBound(Expr *E); |
| bool RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser); |
| bool RequireCompleteExprType(Expr *E, unsigned DiagID); |
| |
| template <typename... Ts> |
| bool RequireCompleteExprType(Expr *E, unsigned DiagID, const Ts &...Args) { |
| BoundTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...); |
| return RequireCompleteExprType(E, Diagnoser); |
| } |
| |
| bool RequireLiteralType(SourceLocation Loc, QualType T, |
| TypeDiagnoser &Diagnoser); |
| bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID); |
| |
| template <typename... Ts> |
| bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID, |
| const Ts &...Args) { |
| BoundTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...); |
| return RequireLiteralType(Loc, T, Diagnoser); |
| } |
| |
| QualType getElaboratedType(ElaboratedTypeKeyword Keyword, |
| const CXXScopeSpec &SS, QualType T, |
| TagDecl *OwnedTagDecl = nullptr); |
| |
| QualType BuildTypeofExprType(Expr *E, SourceLocation Loc); |
| /// If AsUnevaluated is false, E is treated as though it were an evaluated |
| /// context, such as when building a type for decltype(auto). |
| QualType BuildDecltypeType(Expr *E, SourceLocation Loc, |
| bool AsUnevaluated = true); |
| QualType BuildUnaryTransformType(QualType BaseType, |
| UnaryTransformType::UTTKind UKind, |
| SourceLocation Loc); |
| |
| //===--------------------------------------------------------------------===// |
| // Symbol table / Decl tracking callbacks: SemaDecl.cpp. |
| // |
| |
| struct SkipBodyInfo { |
| SkipBodyInfo() |
| : ShouldSkip(false), CheckSameAsPrevious(false), Previous(nullptr), |
| New(nullptr) {} |
| bool ShouldSkip; |
| bool CheckSameAsPrevious; |
| NamedDecl *Previous; |
| NamedDecl *New; |
| }; |
| |
| DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr); |
| |
| void DiagnoseUseOfUnimplementedSelectors(); |
| |
| bool isSimpleTypeSpecifier(tok::TokenKind Kind) const; |
| |
| ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, |
| Scope *S, CXXScopeSpec *SS = nullptr, |
| bool isClassName = false, bool HasTrailingDot = false, |
| ParsedType ObjectType = nullptr, |
| bool IsCtorOrDtorName = false, |
| bool WantNontrivialTypeSourceInfo = false, |
| bool IsClassTemplateDeductionContext = true, |
| IdentifierInfo **CorrectedII = nullptr); |
| TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S); |
| bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S); |
| void DiagnoseUnknownTypeName(IdentifierInfo *&II, |
| SourceLocation IILoc, |
| Scope *S, |
| CXXScopeSpec *SS, |
| ParsedType &SuggestedType, |
| bool IsTemplateName = false); |
| |
| /// Attempt to behave like MSVC in situations where lookup of an unqualified |
| /// type name has failed in a dependent context. In these situations, we |
| /// automatically form a DependentTypeName that will retry lookup in a related |
| /// scope during instantiation. |
| ParsedType ActOnMSVCUnknownTypeName(const IdentifierInfo &II, |
| SourceLocation NameLoc, |
| bool IsTemplateTypeArg); |
| |
| /// Describes the result of the name lookup and resolution performed |
| /// by \c ClassifyName(). |
| enum NameClassificationKind { |
| /// This name is not a type or template in this context, but might be |
| /// something else. |
| NC_Unknown, |
| /// Classification failed; an error has been produced. |
| NC_Error, |
| /// The name has been typo-corrected to a keyword. |
| NC_Keyword, |
| /// The name was classified as a type. |
| NC_Type, |
| /// The name was classified as a specific non-type, non-template |
| /// declaration. ActOnNameClassifiedAsNonType should be called to |
| /// convert the declaration to an expression. |
| NC_NonType, |
| /// The name was classified as an ADL-only function name. |
| /// ActOnNameClassifiedAsUndeclaredNonType should be called to convert the |
| /// result to an expression. |
| NC_UndeclaredNonType, |
| /// The name denotes a member of a dependent type that could not be |
| /// resolved. ActOnNameClassifiedAsDependentNonType should be called to |
| /// convert the result to an expression. |
| NC_DependentNonType, |
| /// The name was classified as a non-type, and an expression representing |
| /// that name has been formed. |
| NC_ContextIndependentExpr, |
| /// The name was classified as a template whose specializations are types. |
| NC_TypeTemplate, |
| /// The name was classified as a variable template name. |
| NC_VarTemplate, |
| /// The name was classified as a function template name. |
| NC_FunctionTemplate, |
| /// The name was classified as an ADL-only function template name. |
| NC_UndeclaredTemplate, |
| }; |
| |
| class NameClassification { |
| NameClassificationKind Kind; |
| union { |
| ExprResult Expr; |
| NamedDecl *NonTypeDecl; |
| TemplateName Template; |
| ParsedType Type; |
| }; |
| |
| explicit NameClassification(NameClassificationKind Kind) : Kind(Kind) {} |
| |
| public: |
| NameClassification(ParsedType Type) : Kind(NC_Type), Type(Type) {} |
| |
| NameClassification(const IdentifierInfo *Keyword) : Kind(NC_Keyword) {} |
| |
| static NameClassification Error() { |
| return NameClassification(NC_Error); |
| } |
| |
| static NameClassification Unknown() { |
| return NameClassification(NC_Unknown); |
| } |
| |
| static NameClassification ContextIndependentExpr(ExprResult E) { |
| NameClassification Result(NC_ContextIndependentExpr); |
| Result.Expr = E; |
| return Result; |
| } |
| |
| static NameClassification NonType(NamedDecl *D) { |
| NameClassification Result(NC_NonType); |
| Result.NonTypeDecl = D; |
| return Result; |
| } |
| |
| static NameClassification UndeclaredNonType() { |
| return NameClassification(NC_UndeclaredNonType); |
| } |
| |
| static NameClassification DependentNonType() { |
| return NameClassification(NC_DependentNonType); |
| } |
| |
| static NameClassification TypeTemplate(TemplateName Name) { |
| NameClassification Result(NC_TypeTemplate); |
| Result.Template = Name; |
| return Result; |
| } |
| |
| static NameClassification VarTemplate(TemplateName Name) { |
| NameClassification Result(NC_VarTemplate); |
| Result.Template = Name; |
| return Result; |
| } |
| |
| static NameClassification FunctionTemplate(TemplateName Name) { |
| NameClassification Result(NC_FunctionTemplate); |
| Result.Template = Name; |
| return Result; |
| } |
| |
| static NameClassification UndeclaredTemplate(TemplateName Name) { |
| NameClassification Result(NC_UndeclaredTemplate); |
| Result.Template = Name; |
| return Result; |
| } |
| |
| NameClassificationKind getKind() const { return Kind; } |
| |
| ExprResult getExpression() const { |
| assert(Kind == NC_ContextIndependentExpr); |
| return Expr; |
| } |
| |
| ParsedType getType() const { |
| assert(Kind == NC_Type); |
| return Type; |
| } |
| |
| NamedDecl *getNonTypeDecl() const { |
| assert(Kind == NC_NonType); |
| return NonTypeDecl; |
| } |
| |
| TemplateName getTemplateName() const { |
| assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate || |
| Kind == NC_VarTemplate || Kind == NC_UndeclaredTemplate); |
| return Template; |
| } |
| |
| TemplateNameKind getTemplateNameKind() const { |
| switch (Kind) { |
| case NC_TypeTemplate: |
| return TNK_Type_template; |
| case NC_FunctionTemplate: |
| return TNK_Function_template; |
| case NC_VarTemplate: |
| return TNK_Var_template; |
| case NC_UndeclaredTemplate: |
| return TNK_Undeclared_template; |
| default: |
| llvm_unreachable("unsupported name classification."); |
| } |
| } |
| }; |
| |
| /// Perform name lookup on the given name, classifying it based on |
| /// the results of name lookup and the following token. |
| /// |
| /// This routine is used by the parser to resolve identifiers and help direct |
| /// parsing. When the identifier cannot be found, this routine will attempt |
| /// to correct the typo and classify based on the resulting name. |
| /// |
| /// \param S The scope in which we're performing name lookup. |
| /// |
| /// \param SS The nested-name-specifier that precedes the name. |
| /// |
| /// \param Name The identifier. If typo correction finds an alternative name, |
| /// this pointer parameter will be updated accordingly. |
| /// |
| /// \param NameLoc The location of the identifier. |
| /// |
| /// \param NextToken The token following the identifier. Used to help |
| /// disambiguate the name. |
| /// |
| /// \param CCC The correction callback, if typo correction is desired. |
| NameClassification ClassifyName(Scope *S, CXXScopeSpec &SS, |
| IdentifierInfo *&Name, SourceLocation NameLoc, |
| const Token &NextToken, |
| CorrectionCandidateCallback *CCC = nullptr); |
| |
| /// Act on the result of classifying a name as an undeclared (ADL-only) |
| /// non-type declaration. |
| ExprResult ActOnNameClassifiedAsUndeclaredNonType(IdentifierInfo *Name, |
| SourceLocation NameLoc); |
| /// Act on the result of classifying a name as an undeclared member of a |
| /// dependent base class. |
| ExprResult ActOnNameClassifiedAsDependentNonType(const CXXScopeSpec &SS, |
| IdentifierInfo *Name, |
| SourceLocation NameLoc, |
| bool IsAddressOfOperand); |
| /// Act on the result of classifying a name as a specific non-type |
| /// declaration. |
| ExprResult ActOnNameClassifiedAsNonType(Scope *S, const CXXScopeSpec &SS, |
| NamedDecl *Found, |
| SourceLocation NameLoc, |
| const Token &NextToken); |
| |
| /// Describes the detailed kind of a template name. Used in diagnostics. |
| enum class TemplateNameKindForDiagnostics { |
| ClassTemplate, |
| FunctionTemplate, |
| VarTemplate, |
| AliasTemplate, |
| TemplateTemplateParam, |
| Concept, |
| DependentTemplate |
| }; |
| TemplateNameKindForDiagnostics |
| getTemplateNameKindForDiagnostics(TemplateName Name); |
| |
| /// Determine whether it's plausible that E was intended to be a |
| /// template-name. |
| bool mightBeIntendedToBeTemplateName(ExprResult E, bool &Dependent) { |
| if (!getLangOpts().CPlusPlus || E.isInvalid()) |
| return false; |
| Dependent = false; |
| if (auto *DRE = dyn_cast<DeclRefExpr>(E.get())) |
| return !DRE->hasExplicitTemplateArgs(); |
| if (auto *ME = dyn_cast<MemberExpr>(E.get())) |
| return !ME->hasExplicitTemplateArgs(); |
| Dependent = true; |
| if (auto *DSDRE = dyn_cast<DependentScopeDeclRefExpr>(E.get())) |
| return !DSDRE->hasExplicitTemplateArgs(); |
| if (auto *DSME = dyn_cast<CXXDependentScopeMemberExpr>(E.get())) |
| return !DSME->hasExplicitTemplateArgs(); |
| // Any additional cases recognized here should also be handled by |
| // diagnoseExprIntendedAsTemplateName. |
| return false; |
| } |
| void diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName, |
| SourceLocation Less, |
| SourceLocation Greater); |
| |
| Decl *ActOnDeclarator(Scope *S, Declarator &D); |
| |
| NamedDecl *HandleDeclarator(Scope *S, Declarator &D, |
| MultiTemplateParamsArg TemplateParameterLists); |
| void RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S); |
| bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info); |
| bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, |
| DeclarationName Name, SourceLocation Loc, |
| bool IsTemplateId); |
| void |
| diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals, |
| SourceLocation FallbackLoc, |
| SourceLocation ConstQualLoc = SourceLocation(), |
| SourceLocation VolatileQualLoc = SourceLocation(), |
| SourceLocation RestrictQualLoc = SourceLocation(), |
| SourceLocation AtomicQualLoc = SourceLocation(), |
| SourceLocation UnalignedQualLoc = SourceLocation()); |
| |
| static bool adjustContextForLocalExternDecl(DeclContext *&DC); |
| void DiagnoseFunctionSpecifiers(const DeclSpec &DS); |
| NamedDecl *getShadowedDeclaration(const TypedefNameDecl *D, |
| const LookupResult &R); |
| NamedDecl *getShadowedDeclaration(const VarDecl *D, const LookupResult &R); |
| void CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, |
| const LookupResult &R); |
| void CheckShadow(Scope *S, VarDecl *D); |
| |
| /// Warn if 'E', which is an expression that is about to be modified, refers |
| /// to a shadowing declaration. |
| void CheckShadowingDeclModification(Expr *E, SourceLocation Loc); |
| |
| void DiagnoseShadowingLambdaDecls(const sema::LambdaScopeInfo *LSI); |
| |
| private: |
| /// Map of current shadowing declarations to shadowed declarations. Warn if |
| /// it looks like the user is trying to modify the shadowing declaration. |
| llvm::DenseMap<const NamedDecl *, const NamedDecl *> ShadowingDecls; |
| |
| public: |
| void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange); |
| void handleTagNumbering(const TagDecl *Tag, Scope *TagScope); |
| void setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec, |
| TypedefNameDecl *NewTD); |
| void CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *D); |
| NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, |
| TypeSourceInfo *TInfo, |
| LookupResult &Previous); |
| NamedDecl* ActOnTypedefNameDecl(Scope* S, DeclContext* DC, TypedefNameDecl *D, |
| LookupResult &Previous, bool &Redeclaration); |
| NamedDecl *ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, |
| TypeSourceInfo *TInfo, |
| LookupResult &Previous, |
| MultiTemplateParamsArg TemplateParamLists, |
| bool &AddToScope, |
| ArrayRef<BindingDecl *> Bindings = None); |
| NamedDecl * |
| ActOnDecompositionDeclarator(Scope *S, Declarator &D, |
| MultiTemplateParamsArg TemplateParamLists); |
| // Returns true if the variable declaration is a redeclaration |
| bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous); |
| void CheckVariableDeclarationType(VarDecl *NewVD); |
| bool DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, |
| Expr *Init); |
| void CheckCompleteVariableDeclaration(VarDecl *VD); |
| void CheckCompleteDecompositionDeclaration(DecompositionDecl *DD); |
| void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D); |
| |
| NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, |
| TypeSourceInfo *TInfo, |
| LookupResult &Previous, |
| MultiTemplateParamsArg TemplateParamLists, |
| bool &AddToScope); |
| bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); |
| |
| enum class CheckConstexprKind { |
| /// Diagnose issues that are non-constant or that are extensions. |
| Diagnose, |
| /// Identify whether this function satisfies the formal rules for constexpr |
| /// functions in the current lanugage mode (with no extensions). |
| CheckValid |
| }; |
| |
| bool CheckConstexprFunctionDefinition(const FunctionDecl *FD, |
| CheckConstexprKind Kind); |
| |
| void DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD); |
| void FindHiddenVirtualMethods(CXXMethodDecl *MD, |
| SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods); |
| void NoteHiddenVirtualMethods(CXXMethodDecl *MD, |
| SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods); |
| // Returns true if the function declaration is a redeclaration |
| bool CheckFunctionDeclaration(Scope *S, |
| FunctionDecl *NewFD, LookupResult &Previous, |
| bool IsMemberSpecialization); |
| bool shouldLinkDependentDeclWithPrevious(Decl *D, Decl *OldDecl); |
| bool canFullyTypeCheckRedeclaration(ValueDecl *NewD, ValueDecl *OldD, |
| QualType NewT, QualType OldT); |
| void CheckMain(FunctionDecl *FD, const DeclSpec &D); |
| void CheckMSVCRTEntryPoint(FunctionDecl *FD); |
| Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, |
| bool IsDefinition); |
| void CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D); |
| Decl *ActOnParamDeclarator(Scope *S, Declarator &D); |
| ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, |
| SourceLocation Loc, |
| QualType T); |
| ParmVarDecl *CheckParameter(DeclContext *DC, SourceLocation StartLoc, |
| SourceLocation NameLoc, IdentifierInfo *Name, |
| QualType T, TypeSourceInfo *TSInfo, |
| StorageClass SC); |
| void ActOnParamDefaultArgument(Decl *param, |
| SourceLocation EqualLoc, |
| Expr *defarg); |
| void ActOnParamUnparsedDefaultArgument(Decl *param, |
| SourceLocation EqualLoc, |
| SourceLocation ArgLoc); |
| void ActOnParamDefaultArgumentError(Decl *param, SourceLocation EqualLoc); |
| bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg, |
| SourceLocation EqualLoc); |
| |
| // Contexts where using non-trivial C union types can be disallowed. This is |
| // passed to err_non_trivial_c_union_in_invalid_context. |
| enum NonTrivialCUnionContext { |
| // Function parameter. |
| NTCUC_FunctionParam, |
| // Function return. |
| NTCUC_FunctionReturn, |
| // Default-initialized object. |
| NTCUC_DefaultInitializedObject, |
| // Variable with automatic storage duration. |
| NTCUC_AutoVar, |
| // Initializer expression that might copy from another object. |
| NTCUC_CopyInit, |
| // Assignment. |
| NTCUC_Assignment, |
| // Compound literal. |
| NTCUC_CompoundLiteral, |
| // Block capture. |
| NTCUC_BlockCapture, |
| // lvalue-to-rvalue conversion of volatile type. |
| NTCUC_LValueToRValueVolatile, |
| }; |
| |
| /// Emit diagnostics if the initializer or any of its explicit or |
| /// implicitly-generated subexpressions require copying or |
| /// default-initializing a type that is or contains a C union type that is |
| /// non-trivial to copy or default-initialize. |
| void checkNonTrivialCUnionInInitializer(const Expr *Init, SourceLocation Loc); |
| |
| // These flags are passed to checkNonTrivialCUnion. |
| enum NonTrivialCUnionKind { |
| NTCUK_Init = 0x1, |
| NTCUK_Destruct = 0x2, |
| NTCUK_Copy = 0x4, |
| }; |
| |
| /// Emit diagnostics if a non-trivial C union type or a struct that contains |
| /// a non-trivial C union is used in an invalid context. |
| void checkNonTrivialCUnion(QualType QT, SourceLocation Loc, |
| NonTrivialCUnionContext UseContext, |
| unsigned NonTrivialKind); |
| |
| void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit); |
| void ActOnUninitializedDecl(Decl *dcl); |
| void ActOnInitializerError(Decl *Dcl); |
| |
| void ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc); |
| void ActOnCXXForRangeDecl(Decl *D); |
| StmtResult ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, |
| IdentifierInfo *Ident, |
| ParsedAttributes &Attrs, |
| SourceLocation AttrEnd); |
| void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc); |
| void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc); |
| void CheckStaticLocalForDllExport(VarDecl *VD); |
| void FinalizeDeclaration(Decl *D); |
| DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, |
| ArrayRef<Decl *> Group); |
| DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef<Decl *> Group); |
| |
| /// Should be called on all declarations that might have attached |
| /// documentation comments. |
| void ActOnDocumentableDecl(Decl *D); |
| void ActOnDocumentableDecls(ArrayRef<Decl *> Group); |
| |
| void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, |
| SourceLocation LocAfterDecls); |
| void CheckForFunctionRedefinition( |
| FunctionDecl *FD, const FunctionDecl *EffectiveDefinition = nullptr, |
| SkipBodyInfo *SkipBody = nullptr); |
| Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D, |
| MultiTemplateParamsArg TemplateParamLists, |
| SkipBodyInfo *SkipBody = nullptr); |
| Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D, |
| SkipBodyInfo *SkipBody = nullptr); |
| void ActOnStartOfObjCMethodDef(Scope *S, Decl *D); |
| bool isObjCMethodDecl(Decl *D) { |
| return D && isa<ObjCMethodDecl>(D); |
| } |
| |
| /// Determine whether we can delay parsing the body of a function or |
| /// function template until it is used, assuming we don't care about emitting |
| /// code for that function. |
| /// |
| /// This will be \c false if we may need the body of the function in the |
| /// middle of parsing an expression (where it's impractical to switch to |
| /// parsing a different function), for instance, if it's constexpr in C++11 |
| /// or has an 'auto' return type in C++14. These cases are essentially bugs. |
| bool canDelayFunctionBody(const Declarator &D); |
| |
| /// Determine whether we can skip parsing the body of a function |
| /// definition, assuming we don't care about analyzing its body or emitting |
| /// code for that function. |
| /// |
| /// This will be \c false only if we may need the body of the function in |
| /// order to parse the rest of the program (for instance, if it is |
| /// \c constexpr in C++11 or has an 'auto' return type in C++14). |
| bool canSkipFunctionBody(Decl *D); |
| |
| void computeNRVO(Stmt *Body, sema::FunctionScopeInfo *Scope); |
| Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body); |
| Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation); |
| Decl *ActOnSkippedFunctionBody(Decl *Decl); |
| void ActOnFinishInlineFunctionDef(FunctionDecl *D); |
| |
| /// ActOnFinishDelayedAttribute - Invoked when we have finished parsing an |
| /// attribute for which parsing is delayed. |
| void ActOnFinishDelayedAttribute(Scope *S, Decl *D, ParsedAttributes &Attrs); |
| |
| /// Diagnose any unused parameters in the given sequence of |
| /// ParmVarDecl pointers. |
| void DiagnoseUnusedParameters(ArrayRef<ParmVarDecl *> Parameters); |
| |
| /// Diagnose whether the size of parameters or return value of a |
| /// function or obj-c method definition is pass-by-value and larger than a |
| /// specified threshold. |
| void |
| DiagnoseSizeOfParametersAndReturnValue(ArrayRef<ParmVarDecl *> Parameters, |
| QualType ReturnTy, NamedDecl *D); |
| |
| void DiagnoseInvalidJumps(Stmt *Body); |
| Decl *ActOnFileScopeAsmDecl(Expr *expr, |
| SourceLocation AsmLoc, |
| SourceLocation RParenLoc); |
| |
| /// Handle a C++11 empty-declaration and attribute-declaration. |
| Decl *ActOnEmptyDeclaration(Scope *S, const ParsedAttributesView &AttrList, |
| SourceLocation SemiLoc); |
| |
| enum class ModuleDeclKind { |
| Interface, ///< 'export module X;' |
| Implementation, ///< 'module X;' |
| }; |
| |
| /// The parser has processed a module-declaration that begins the definition |
| /// of a module interface or implementation. |
| DeclGroupPtrTy ActOnModuleDecl(SourceLocation StartLoc, |
| SourceLocation ModuleLoc, ModuleDeclKind MDK, |
| ModuleIdPath Path, bool IsFirstDecl); |
| |
| /// The parser has processed a global-module-fragment declaration that begins |
| /// the definition of the global module fragment of the current module unit. |
| /// \param ModuleLoc The location of the 'module' keyword. |
| DeclGroupPtrTy ActOnGlobalModuleFragmentDecl(SourceLocation ModuleLoc); |
| |
| /// The parser has processed a private-module-fragment declaration that begins |
| /// the definition of the private module fragment of the current module unit. |
| /// \param ModuleLoc The location of the 'module' keyword. |
| /// \param PrivateLoc The location of the 'private' keyword. |
| DeclGroupPtrTy ActOnPrivateModuleFragmentDecl(SourceLocation ModuleLoc, |
| SourceLocation PrivateLoc); |
| |
| /// The parser has processed a module import declaration. |
| /// |
| /// \param StartLoc The location of the first token in the declaration. This |
| /// could be the location of an '@', 'export', or 'import'. |
| /// \param ExportLoc The location of the 'export' keyword, if any. |
| /// \param ImportLoc The location of the 'import' keyword. |
| /// \param Path The module access path. |
| DeclResult ActOnModuleImport(SourceLocation StartLoc, |
| SourceLocation ExportLoc, |
| SourceLocation ImportLoc, ModuleIdPath Path); |
| DeclResult ActOnModuleImport(SourceLocation StartLoc, |
| SourceLocation ExportLoc, |
| SourceLocation ImportLoc, Module *M, |
| ModuleIdPath Path = {}); |
| |
| /// The parser has processed a module import translated from a |
| /// #include or similar preprocessing directive. |
| void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod); |
| void BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod); |
| |
| /// The parsed has entered a submodule. |
| void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod); |
| /// The parser has left a submodule. |
| void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod); |
| |
| /// Create an implicit import of the given module at the given |
| /// source location, for error recovery, if possible. |
| /// |
| /// This routine is typically used when an entity found by name lookup |
| /// is actually hidden within a module that we know about but the user |
| /// has forgotten to import. |
| void createImplicitModuleImportForErrorRecovery(SourceLocation Loc, |
| Module *Mod); |
| |
| /// Kinds of missing import. Note, the values of these enumerators correspond |
| /// to %select values in diagnostics. |
| enum class MissingImportKind { |
| Declaration, |
| Definition, |
| DefaultArgument, |
| ExplicitSpecialization, |
| PartialSpecialization |
| }; |
| |
| /// Diagnose that the specified declaration needs to be visible but |
| /// isn't, and suggest a module import that would resolve the problem. |
| void diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl, |
| MissingImportKind MIK, bool Recover = true); |
| void diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl, |
| SourceLocation DeclLoc, ArrayRef<Module *> Modules, |
| MissingImportKind MIK, bool Recover); |
| |
| Decl *ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc, |
| SourceLocation LBraceLoc); |
| Decl *ActOnFinishExportDecl(Scope *S, Decl *ExportDecl, |
| SourceLocation RBraceLoc); |
| |
| /// We've found a use of a templated declaration that would trigger an |
| /// implicit instantiation. Check that any relevant explicit specializations |
| /// and partial specializations are visible, and diagnose if not. |
| void checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec); |
| |
| /// We've found a use of a template specialization that would select a |
| /// partial specialization. Check that the partial specialization is visible, |
| /// and diagnose if not. |
| void checkPartialSpecializationVisibility(SourceLocation Loc, |
| NamedDecl *Spec); |
| |
| /// Retrieve a suitable printing policy for diagnostics. |
| PrintingPolicy getPrintingPolicy() const { |
| return getPrintingPolicy(Context, PP); |
| } |
| |
| /// Retrieve a suitable printing policy for diagnostics. |
| static PrintingPolicy getPrintingPolicy(const ASTContext &Ctx, |
| const Preprocessor &PP); |
| |
| /// Scope actions. |
| void ActOnPopScope(SourceLocation Loc, Scope *S); |
| void ActOnTranslationUnitScope(Scope *S); |
| |
| Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, |
| RecordDecl *&AnonRecord); |
| Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, |
| MultiTemplateParamsArg TemplateParams, |
| bool IsExplicitInstantiation, |
| RecordDecl *&AnonRecord); |
| |
| Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, |
| AccessSpecifier AS, |
| RecordDecl *Record, |
| const PrintingPolicy &Policy); |
| |
| Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, |
| RecordDecl *Record); |
| |
| /// Common ways to introduce type names without a tag for use in diagnostics. |
| /// Keep in sync with err_tag_reference_non_tag. |
| enum NonTagKind { |
| NTK_NonStruct, |
| NTK_NonClass, |
| NTK_NonUnion, |
| NTK_NonEnum, |
| NTK_Typedef, |
| NTK_TypeAlias, |
| NTK_Template, |
| NTK_TypeAliasTemplate, |
| NTK_TemplateTemplateArgument, |
| }; |
| |
| /// Given a non-tag type declaration, returns an enum useful for indicating |
| /// what kind of non-tag type this is. |
| NonTagKind getNonTagTypeDeclKind(const Decl *D, TagTypeKind TTK); |
| |
| bool isAcceptableTagRedeclaration(const TagDecl *Previous, |
| TagTypeKind NewTag, bool isDefinition, |
| SourceLocation NewTagLoc, |
| const IdentifierInfo *Name); |
| |
| enum TagUseKind { |
| TUK_Reference, // Reference to a tag: 'struct foo *X;' |
| TUK_Declaration, // Fwd decl of a tag: 'struct foo;' |
| TUK_Definition, // Definition of a tag: 'struct foo { int X; } Y;' |
| TUK_Friend // Friend declaration: 'friend struct foo;' |
| }; |
| |
| Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, |
| SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, |
| SourceLocation NameLoc, const ParsedAttributesView &Attr, |
| AccessSpecifier AS, SourceLocation ModulePrivateLoc, |
| MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, |
| bool &IsDependent, SourceLocation ScopedEnumKWLoc, |
| bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, |
| bool IsTypeSpecifier, bool IsTemplateParamOrArg, |
| SkipBodyInfo *SkipBody = nullptr); |
| |
| Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, |
| unsigned TagSpec, SourceLocation TagLoc, |
| CXXScopeSpec &SS, IdentifierInfo *Name, |
| SourceLocation NameLoc, |
| const ParsedAttributesView &Attr, |
| MultiTemplateParamsArg TempParamLists); |
| |
| TypeResult ActOnDependentTag(Scope *S, |
| unsigned TagSpec, |
| TagUseKind TUK, |
| const CXXScopeSpec &SS, |
| IdentifierInfo *Name, |
| SourceLocation TagLoc, |
| SourceLocation NameLoc); |
| |
| void ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, |
| IdentifierInfo *ClassName, |
| SmallVectorImpl<Decl *> &Decls); |
| Decl *ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, |
| Declarator &D, Expr *BitfieldWidth); |
| |
| FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart, |
| Declarator &D, Expr *BitfieldWidth, |
| InClassInitStyle InitStyle, |
| AccessSpecifier AS); |
| MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD, |
| SourceLocation DeclStart, Declarator &D, |
| Expr *BitfieldWidth, |
| InClassInitStyle InitStyle, |
| AccessSpecifier AS, |
| const ParsedAttr &MSPropertyAttr); |
| |
| FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T, |
| TypeSourceInfo *TInfo, |
| RecordDecl *Record, SourceLocation Loc, |
| bool Mutable, Expr *BitfieldWidth, |
| InClassInitStyle InitStyle, |
| SourceLocation TSSL, |
| AccessSpecifier AS, NamedDecl *PrevDecl, |
| Declarator *D = nullptr); |
| |
| bool CheckNontrivialField(FieldDecl *FD); |
| void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM); |
| |
| enum TrivialABIHandling { |
| /// The triviality of a method unaffected by "trivial_abi". |
| TAH_IgnoreTrivialABI, |
| |
| /// The triviality of a method affected by "trivial_abi". |
| TAH_ConsiderTrivialABI |
| }; |
| |
| bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, |
| TrivialABIHandling TAH = TAH_IgnoreTrivialABI, |
| bool Diagnose = false); |
| |
| /// For a defaulted function, the kind of defaulted function that it is. |
| class DefaultedFunctionKind { |
| CXXSpecialMember SpecialMember : 8; |
| DefaultedComparisonKind Comparison : 8; |
| |
| public: |
| DefaultedFunctionKind() |
| : SpecialMember(CXXInvalid), Comparison(DefaultedComparisonKind::None) { |
| } |
| DefaultedFunctionKind(CXXSpecialMember CSM) |
| : SpecialMember(CSM), Comparison(DefaultedComparisonKind::None) {} |
| DefaultedFunctionKind(DefaultedComparisonKind Comp) |
| : SpecialMember(CXXInvalid), Comparison(Comp) {} |
| |
| bool isSpecialMember() const { return SpecialMember != CXXInvalid; } |
| bool isComparison() const { |
| return Comparison != DefaultedComparisonKind::None; |
| } |
| |
| explicit operator bool() const { |
| return isSpecialMember() || isComparison(); |
| } |
| |
| CXXSpecialMember asSpecialMember() const { return SpecialMember; } |
| DefaultedComparisonKind asComparison() const { return Comparison; } |
| |
| /// Get the index of this function kind for use in diagnostics. |
| unsigned getDiagnosticIndex() const { |
| static_assert(CXXInvalid > CXXDestructor, |
| "invalid should have highest index"); |
| static_assert((unsigned)DefaultedComparisonKind::None == 0, |
| "none should be equal to zero"); |
| return SpecialMember + (unsigned)Comparison; |
| } |
| }; |
| |
| DefaultedFunctionKind getDefaultedFunctionKind(const FunctionDecl *FD); |
| |
| CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD) { |
| return getDefaultedFunctionKind(MD).asSpecialMember(); |
| } |
| DefaultedComparisonKind getDefaultedComparisonKind(const FunctionDecl *FD) { |
| return getDefaultedFunctionKind(FD).asComparison(); |
| } |
| |
| void ActOnLastBitfield(SourceLocation DeclStart, |
| SmallVectorImpl<Decl *> &AllIvarDecls); |
| Decl *ActOnIvar(Scope *S, SourceLocation DeclStart, |
| Declarator &D, Expr *BitfieldWidth, |
| tok::ObjCKeywordKind visibility); |
| |
| // This is used for both record definitions and ObjC interface declarations. |
| void ActOnFields(Scope *S, SourceLocation RecLoc, Decl *TagDecl, |
| ArrayRef<Decl *> Fields, SourceLocation LBrac, |
| SourceLocation RBrac, const ParsedAttributesView &AttrList); |
| |
| /// ActOnTagStartDefinition - Invoked when we have entered the |
| /// scope of a tag's definition (e.g., for an enumeration, class, |
| /// struct, or union). |
| void ActOnTagStartDefinition(Scope *S, Decl *TagDecl); |
| |
| /// Perform ODR-like check for C/ObjC when merging tag types from modules. |
| /// Differently from C++, actually parse the body and reject / error out |
| /// in case of a structural mismatch. |
| bool ActOnDuplicateDefinition(DeclSpec &DS, Decl *Prev, |
| SkipBodyInfo &SkipBody); |
| |
| typedef void *SkippedDefinitionContext; |
| |
| /// Invoked when we enter a tag definition that we're skipping. |
| SkippedDefinitionContext ActOnTagStartSkippedDefinition(Scope *S, Decl *TD); |
| |
| Decl *ActOnObjCContainerStartDefinition(Decl *IDecl); |
| |
| /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a |
| /// C++ record definition's base-specifiers clause and are starting its |
| /// member declarations. |
| void ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagDecl, |
| SourceLocation FinalLoc, |
| bool IsFinalSpelledSealed, |
| SourceLocation LBraceLoc); |
| |
| /// ActOnTagFinishDefinition - Invoked once we have finished parsing |
| /// the definition of a tag (enumeration, class, struct, or union). |
| void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl, |
| SourceRange BraceRange); |
| |
| void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context); |
| |
| void ActOnObjCContainerFinishDefinition(); |
| |
| /// Invoked when we must temporarily exit the objective-c container |
| /// scope for parsing/looking-up C constructs. |
| /// |
| /// Must be followed by a call to \see ActOnObjCReenterContainerContext |
| void ActOnObjCTemporaryExitContainerContext(DeclContext *DC); |
| void ActOnObjCReenterContainerContext(DeclContext *DC); |
| |
| /// ActOnTagDefinitionError - Invoked when there was an unrecoverable |
| /// error parsing the definition of a tag. |
| void ActOnTagDefinitionError(Scope *S, Decl *TagDecl); |
| |
| EnumConstantDecl *CheckEnumConstant(EnumDecl *Enum, |
| EnumConstantDecl *LastEnumConst, |
| SourceLocation IdLoc, |
| IdentifierInfo *Id, |
| Expr *val); |
| bool CheckEnumUnderlyingType(TypeSourceInfo *TI); |
| bool CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, |
| QualType EnumUnderlyingTy, bool IsFixed, |
| const EnumDecl *Prev); |
| |
| /// Determine whether the body of an anonymous enumeration should be skipped. |
| /// \param II The name of the first enumerator. |
| SkipBodyInfo shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II, |
| SourceLocation IILoc); |
| |
| Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant, |
| SourceLocation IdLoc, IdentifierInfo *Id, |
| const ParsedAttributesView &Attrs, |
| SourceLocation EqualLoc, Expr *Val); |
| void ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, |
| Decl *EnumDecl, ArrayRef<Decl *> Elements, Scope *S, |
| const ParsedAttributesView &Attr); |
| |
| DeclContext *getContainingDC(DeclContext *DC); |
| |
| /// Set the current declaration context until it gets popped. |
| void PushDeclContext(Scope *S, DeclContext *DC); |
| void PopDeclContext(); |
| |
| /// EnterDeclaratorContext - Used when we must lookup names in the context |
| /// of a declarator's nested name specifier. |
| void EnterDeclaratorContext(Scope *S, DeclContext *DC); |
| void ExitDeclaratorContext(Scope *S); |
| |
| /// Push the parameters of D, which must be a function, into scope. |
| void ActOnReenterFunctionContext(Scope* S, Decl* D); |
| void ActOnExitFunctionContext(); |
| |
| DeclContext *getFunctionLevelDeclContext(); |
| |
| /// getCurFunctionDecl - If inside of a function body, this returns a pointer |
| /// to the function decl for the function being parsed. If we're currently |
| /// in a 'block', this returns the containing context. |
| FunctionDecl *getCurFunctionDecl(); |
| |
| /// getCurMethodDecl - If inside of a method body, this returns a pointer to |
| /// the method decl for the method being parsed. If we're currently |
| /// in a 'block', this returns the containing context. |
| ObjCMethodDecl *getCurMethodDecl(); |
| |
| /// getCurFunctionOrMethodDecl - Return the Decl for the current ObjC method |
| /// or C function we're in, otherwise return null. If we're currently |
| /// in a 'block', this returns the containing context. |
| NamedDecl *getCurFunctionOrMethodDecl(); |
| |
| /// Add this decl to the scope shadowed decl chains. |
| void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true); |
| |
| /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true |
| /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns |
| /// true if 'D' belongs to the given declaration context. |
| /// |
| /// \param AllowInlineNamespace If \c true, allow the declaration to be in the |
| /// enclosing namespace set of the context, rather than contained |
| /// directly within it. |
| bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S = nullptr, |
| bool AllowInlineNamespace = false); |
| |
| /// Finds the scope corresponding to the given decl context, if it |
| /// happens to be an enclosing scope. Otherwise return NULL. |
| static Scope *getScopeForDeclContext(Scope *S, DeclContext *DC); |
| |
| /// Subroutines of ActOnDeclarator(). |
| TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T, |
| TypeSourceInfo *TInfo); |
| bool isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New); |
| |
| /// Describes the kind of merge to perform for availability |
| /// attributes (including "deprecated", "unavailable", and "availability"). |
| enum AvailabilityMergeKind { |
| /// Don't merge availability attributes at all. |
| AMK_None, |
| /// Merge availability attributes for a redeclaration, which requires |
| /// an exact match. |
| AMK_Redeclaration, |
| /// Merge availability attributes for an override, which requires |
| /// an exact match or a weakening of constraints. |
| AMK_Override, |
| /// Merge availability attributes for an implementation of |
| /// a protocol requirement. |
| AMK_ProtocolImplementation, |
| }; |
| |
| /// Describes the kind of priority given to an availability attribute. |
| /// |
| /// The sum of priorities deteremines the final priority of the attribute. |
| /// The final priority determines how the attribute will be merged. |
| /// An attribute with a lower priority will always remove higher priority |
| /// attributes for the specified platform when it is being applied. An |
| /// attribute with a higher priority will not be applied if the declaration |
| /// already has an availability attribute with a lower priority for the |
| /// specified platform. The final prirority values are not expected to match |
| /// the values in this enumeration, but instead should be treated as a plain |
| /// integer value. This enumeration just names the priority weights that are |
| /// used to calculate that final vaue. |
| enum AvailabilityPriority : int { |
| /// The availability attribute was specified explicitly next to the |
| /// declaration. |
| AP_Explicit = 0, |
| |
| /// The availability attribute was applied using '#pragma clang attribute'. |
| AP_PragmaClangAttribute = 1, |
| |
| /// The availability attribute for a specific platform was inferred from |
| /// an availability attribute for another platform. |
| AP_InferredFromOtherPlatform = 2 |
| }; |
| |
| /// Attribute merging methods. Return true if a new attribute was added. |
| AvailabilityAttr * |
| mergeAvailabilityAttr(NamedDecl *D, const AttributeCommonInfo &CI, |
| IdentifierInfo *Platform, bool Implicit, |
| VersionTuple Introduced, VersionTuple Deprecated, |
| VersionTuple Obsoleted, bool IsUnavailable, |
| StringRef Message, bool IsStrict, StringRef Replacement, |
| AvailabilityMergeKind AMK, int Priority); |
| TypeVisibilityAttr * |
| mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI, |
| TypeVisibilityAttr::VisibilityType Vis); |
| VisibilityAttr *mergeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI, |
| VisibilityAttr::VisibilityType Vis); |
| UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI, |
| StringRef Uuid); |
| DLLImportAttr *mergeDLLImportAttr(Decl *D, const AttributeCommonInfo &CI); |
| DLLExportAttr *mergeDLLExportAttr(Decl *D, const AttributeCommonInfo &CI); |
| MSInheritanceAttr * |
| mergeMSInheritanceAttr(Decl *D, const AttributeCommonInfo &CI, bool BestCase, |
| MSInheritanceAttr::Spelling SemanticSpelling); |
| FormatAttr *mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI, |
| IdentifierInfo *Format, int FormatIdx, |
| int FirstArg); |
| SectionAttr *mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI, |
| StringRef Name); |
| CodeSegAttr *mergeCodeSegAttr(Decl *D, const AttributeCommonInfo &CI, |
| StringRef Name); |
| AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D, |
| const AttributeCommonInfo &CI, |
| const IdentifierInfo *Ident); |
| MinSizeAttr *mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI); |
| NoSpeculativeLoadHardeningAttr * |
| mergeNoSpeculativeLoadHardeningAttr(Decl *D, |
| const NoSpeculativeLoadHardeningAttr &AL); |
| SpeculativeLoadHardeningAttr * |
| mergeSpeculativeLoadHardeningAttr(Decl *D, |
| const SpeculativeLoadHardeningAttr &AL); |
| OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D, |
| const AttributeCommonInfo &CI); |
| InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL); |
| InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, |
| const InternalLinkageAttr &AL); |
| CommonAttr *mergeCommonAttr(Decl *D, const ParsedAttr &AL); |
| CommonAttr *mergeCommonAttr(Decl *D, const CommonAttr &AL); |
| |
| void mergeDeclAttributes(NamedDecl *New, Decl *Old, |
| AvailabilityMergeKind AMK = AMK_Redeclaration); |
| void MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, |
| LookupResult &OldDecls); |
| bool MergeFunctionDecl(FunctionDecl *New, NamedDecl *&Old, Scope *S, |
| bool MergeTypeWithOld); |
| bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, |
| Scope *S, bool MergeTypeWithOld); |
| void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old); |
| void MergeVarDecl(VarDecl *New, LookupResult &Previous); |
| void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld); |
| void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old); |
| bool checkVarDeclRedefinition(VarDecl *OldDefn, VarDecl *NewDefn); |
| void notePreviousDefinition(const NamedDecl *Old, SourceLocation New); |
| bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S); |
| |
| // AssignmentAction - This is used by all the assignment diagnostic functions |
| // to represent what is actually causing the operation |
| enum AssignmentAction { |
| AA_Assigning, |
| AA_Passing, |
| AA_Returning, |
| AA_Converting, |
| AA_Initializing, |
| AA_Sending, |
| AA_Casting, |
| AA_Passing_CFAudited |
| }; |
| |
| /// C++ Overloading. |
| enum OverloadKind { |
| /// This is a legitimate overload: the existing declarations are |
| /// functions or function templates with different signatures. |
| Ovl_Overload, |
| |
| /// This is not an overload because the signature exactly matches |
| /// an existing declaration. |
| Ovl_Match, |
| |
| /// This is not an overload because the lookup results contain a |
| /// non-function. |
| Ovl_NonFunction |
| }; |
| OverloadKind CheckOverload(Scope *S, |
| FunctionDecl *New, |
| const LookupResult &OldDecls, |
| NamedDecl *&OldDecl, |
| bool IsForUsingDecl); |
| bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl, |
| bool ConsiderCudaAttrs = true); |
| |
| ImplicitConversionSequence |
| TryImplicitConversion(Expr *From, QualType ToType, |
| bool SuppressUserConversions, |
| bool AllowExplicit, |
| bool InOverloadResolution, |
| bool CStyle, |
| |